Commit e5ac1167 authored by Rich Prohaska's avatar Rich Prohaska Committed by Yoni Fogel

refs #5333 redo hot expand int and unsigned int

git-svn-id: file:///svn/mysql/tokudb-engine/tokudb-engine@47608 c7de825b-a66e-492c-adef-691d508d4ae1
parent 3d6a6885
......@@ -784,11 +784,23 @@ change_length_is_supported(TABLE *table, TABLE *altered_table, Alter_inplace_inf
return false;
}
static bool
is_sorted(Dynamic_array<uint> &a) {
bool r = true;
if (a.elements() > 0) {
uint lastelement = a.at(0);
for (uint i = 1; i < a.elements(); i++)
if (lastelement > a.at(i))
r = false;
}
return r;
}
int
ha_tokudb::alter_table_expand_columns(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
int error = 0;
tokudb_alter_ctx *ctx = static_cast<tokudb_alter_ctx *>(ha_alter_info->handler_ctx);
assert(ctx->changed_fields.elements() <= 1);
assert(is_sorted(ctx->changed_fields)); // since we build the changed_fields array in field order, it must be sorted
for (int ai = 0; error == 0 && ai < ctx->changed_fields.elements(); ai++) {
uint expand_field_num = ctx->changed_fields.at(ai);
error = alter_table_expand_one_column(altered_table, ha_alter_info, expand_field_num);
......@@ -840,29 +852,32 @@ ha_tokudb::alter_table_expand_one_column(TABLE *altered_table, Alter_inplace_inf
TOKU_TYPE new_field_type = mysql_to_toku_type(new_field);
assert(old_field_type == new_field_type);
uchar operation;
switch (old_field_type) {
case toku_type_int:
assert(is_unsigned(old_field) == is_unsigned(new_field));
if (is_unsigned(old_field))
operation = UPDATE_OP_EXPAND_UINT;
else
operation = UPDATE_OP_EXPAND_INT;
break;
case toku_type_fixstring:
operation = UPDATE_OP_EXPAND_CHAR;
break;
case toku_type_fixbinary:
operation = UPDATE_OP_EXPAND_BINARY;
break;
default:
assert(0);
}
uint32_t curr_num_DBs = table->s->keys + test(hidden_primary_key);
for (uint32_t i = 0; i < curr_num_DBs; i++) {
if (i == primary_key || table_share->key_info[i].flags & HA_CLUSTERING) {
uchar operation;
// make the expand int field message
DBT expand;
memset(&expand, 0, sizeof(expand));
expand.size = 1+4+4+4+4;
switch (old_field_type) {
case toku_type_int:
operation = UPDATE_OP_EXPAND_INT;
expand.size += 1;
break;
case toku_type_fixstring:
operation = UPDATE_OP_EXPAND_CHAR;
break;
case toku_type_fixbinary:
operation = UPDATE_OP_EXPAND_BINARY;
break;
default:
assert(0);
}
expand.data = my_malloc(expand.size, MYF(MY_WME));
if (!expand.data) {
error = ENOMEM;
......@@ -872,7 +887,7 @@ ha_tokudb::alter_table_expand_one_column(TABLE *altered_table, Alter_inplace_inf
expand_ptr[0] = operation;
expand_ptr += sizeof (uchar);
uint32_t old_offset = field_offset(table_share->null_bytes, ctx->table_kc_info, i, expand_field_num);
uint32_t old_offset = field_offset(table_share->null_bytes, ctx->altered_table_kc_info, i, expand_field_num);
memcpy(expand_ptr, &old_offset, sizeof old_offset);
expand_ptr += sizeof old_offset;
......@@ -890,19 +905,6 @@ ha_tokudb::alter_table_expand_one_column(TABLE *altered_table, Alter_inplace_inf
memcpy(expand_ptr, &new_length, sizeof new_length);
expand_ptr += sizeof new_length;
switch (operation) {
case UPDATE_OP_EXPAND_INT:
assert(is_unsigned(old_field) == is_unsigned(new_field));
expand_ptr[0] = is_unsigned(old_field);
expand_ptr += sizeof (uchar);
break;
case UPDATE_OP_EXPAND_CHAR:
case UPDATE_OP_EXPAND_BINARY:
break;
default:
assert(0);
}
assert(expand_ptr == (uchar *)expand.data + expand.size);
// and broadcast it into the tree
......@@ -916,7 +918,7 @@ ha_tokudb::alter_table_expand_one_column(TABLE *altered_table, Alter_inplace_inf
return error;
}
// Return true if the MySQL type is an int type
// Return true if the MySQL type is an int or unsigned int type
static bool
is_int_type(enum_field_types t) {
switch (t) {
......
......@@ -3,10 +3,11 @@ enum {
UPDATE_OP_COL_ADD_OR_DROP = 0,
UPDATE_OP_EXPAND_VARCHAR_OFFSETS = 1,
UPDATE_OP_EXPAND_INT = 2,
UPDATE_OP_EXPAND_CHAR = 3,
UPDATE_OP_EXPAND_BINARY = 4,
UPDATE_OP_ADD_INT = 5,
UPDATE_OP_SUB_INT = 6,
UPDATE_OP_EXPAND_UINT = 3,
UPDATE_OP_EXPAND_CHAR = 4,
UPDATE_OP_EXPAND_BINARY = 5,
UPDATE_OP_ADD_INT = 6,
UPDATE_OP_SUB_INT = 7,
};
#define UP_COL_ADD_OR_DROP UPDATE_OP_COL_ADD_OR_DROP
......@@ -62,13 +63,11 @@ enum {
// offset_start 4 starting offset of the variable length field offsets
// offset end 4 ending offset of the variable length field offsets
// operation 1 == UPDATE_OP_EXPAND_INT, UPDATE_OP_EXPAND_CHAR, UPDATE_OP_EXPAND_BINARY
// operation 1 == UPDATE_OP_EXPAND_INT, UPDATE_OP_EXPAND_UINT, UPDATE_OP_EXPAND_CHAR, UPDATE_OP_EXPAND_BINARY
// old offset 4
// old length 4
// new offset 4
// new length 4
// if operation == UPDATE_OP_EXPAND_INT
// is unsigned 1
// operation 1 == UPDATE_OP_INT_ADD or UPDATE_OP_INT_SUB
// offset 4 starting offset of the int type field
......@@ -719,9 +718,8 @@ tokudb_expand_field(
uchar *extra_pos = (uchar *)extra->data;
uchar operation = extra_pos[0];
assert(operation == UPDATE_OP_EXPAND_INT ||
operation == UPDATE_OP_EXPAND_CHAR ||
operation == UPDATE_OP_EXPAND_BINARY);
assert(operation == UPDATE_OP_EXPAND_INT || operation == UPDATE_OP_EXPAND_UINT ||
operation == UPDATE_OP_EXPAND_CHAR || operation == UPDATE_OP_EXPAND_BINARY);
extra_pos += sizeof operation;
uint32_t old_offset;
......@@ -740,22 +738,7 @@ tokudb_expand_field(
memcpy(&new_length, extra_pos, sizeof new_length);
extra_pos += sizeof new_length;
uchar is_unsigned; // for int expansion
switch (operation) {
case UPDATE_OP_EXPAND_INT:
is_unsigned = extra_pos[0];
extra_pos += sizeof is_unsigned;
assert(is_unsigned == 0 || is_unsigned == 1);
break;
case UPDATE_OP_EXPAND_CHAR:
case UPDATE_OP_EXPAND_BINARY:
break;
default:
assert(0);
}
assert(extra_pos == (uchar *)extra->data + extra->size); // consumed the entire message
assert(old_offset == new_offset); // only expand one field per update, so the offset must be the same
assert(new_length >= old_length); // expand only
assert(old_offset + old_length <= old_val->size); // old field within the old val
......@@ -783,14 +766,16 @@ tokudb_expand_field(
// read the old field, expand it, write to the new offset
switch (operation) {
case UPDATE_OP_EXPAND_INT:
if (is_unsigned) {
if (old_val_ptr[old_length-1] & 0x80) // if sign bit on then sign extend
memset(new_val_ptr, 0xff, new_length);
else
memset(new_val_ptr, 0, new_length);
} else {
if (old_val_ptr[old_length-1] & 0x80) // sign bit on?
memset(new_val_ptr, 0xff, new_length); // sign extend
else
memset(new_val_ptr, 0, new_length);
}
memcpy(new_val_ptr, old_val_ptr, old_length);
new_val_ptr += new_length;
old_val_ptr += old_length;
break;
case UPDATE_OP_EXPAND_UINT:
memset(new_val_ptr, 0, new_length);
memcpy(new_val_ptr, old_val_ptr, old_length);
new_val_ptr += new_length;
old_val_ptr += old_length;
......@@ -854,6 +839,7 @@ tokudb_update_fun(
error = tokudb_expand_varchar_offsets(db, key, old_val, extra, set_val, set_extra);
break;
case UPDATE_OP_EXPAND_INT:
case UPDATE_OP_EXPAND_UINT:
case UPDATE_OP_EXPAND_CHAR:
case UPDATE_OP_EXPAND_BINARY:
error = tokudb_expand_field(db, key, old_val, extra, set_val, set_extra);
......
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