Commit 505a4ec6 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 188106ec
...@@ -784,11 +784,23 @@ change_length_is_supported(TABLE *table, TABLE *altered_table, Alter_inplace_inf ...@@ -784,11 +784,23 @@ change_length_is_supported(TABLE *table, TABLE *altered_table, Alter_inplace_inf
return false; 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 int
ha_tokudb::alter_table_expand_columns(TABLE *altered_table, Alter_inplace_info *ha_alter_info) { ha_tokudb::alter_table_expand_columns(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
int error = 0; int error = 0;
tokudb_alter_ctx *ctx = static_cast<tokudb_alter_ctx *>(ha_alter_info->handler_ctx); 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++) { for (int ai = 0; error == 0 && ai < ctx->changed_fields.elements(); ai++) {
uint expand_field_num = ctx->changed_fields.at(ai); uint expand_field_num = ctx->changed_fields.at(ai);
error = alter_table_expand_one_column(altered_table, ha_alter_info, expand_field_num); 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 ...@@ -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); TOKU_TYPE new_field_type = mysql_to_toku_type(new_field);
assert(old_field_type == new_field_type); 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); uint32_t curr_num_DBs = table->s->keys + test(hidden_primary_key);
for (uint32_t i = 0; i < curr_num_DBs; i++) { for (uint32_t i = 0; i < curr_num_DBs; i++) {
if (i == primary_key || table_share->key_info[i].flags & HA_CLUSTERING) { if (i == primary_key || table_share->key_info[i].flags & HA_CLUSTERING) {
uchar operation;
// make the expand int field message // make the expand int field message
DBT expand; DBT expand;
memset(&expand, 0, sizeof(expand)); memset(&expand, 0, sizeof(expand));
expand.size = 1+4+4+4+4; 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)); expand.data = my_malloc(expand.size, MYF(MY_WME));
if (!expand.data) { if (!expand.data) {
error = ENOMEM; error = ENOMEM;
...@@ -872,7 +887,7 @@ ha_tokudb::alter_table_expand_one_column(TABLE *altered_table, Alter_inplace_inf ...@@ -872,7 +887,7 @@ ha_tokudb::alter_table_expand_one_column(TABLE *altered_table, Alter_inplace_inf
expand_ptr[0] = operation; expand_ptr[0] = operation;
expand_ptr += sizeof (uchar); 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); memcpy(expand_ptr, &old_offset, sizeof old_offset);
expand_ptr += 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 ...@@ -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); memcpy(expand_ptr, &new_length, sizeof new_length);
expand_ptr += 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); assert(expand_ptr == (uchar *)expand.data + expand.size);
// and broadcast it into the tree // and broadcast it into the tree
...@@ -916,7 +918,7 @@ ha_tokudb::alter_table_expand_one_column(TABLE *altered_table, Alter_inplace_inf ...@@ -916,7 +918,7 @@ ha_tokudb::alter_table_expand_one_column(TABLE *altered_table, Alter_inplace_inf
return error; 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 static bool
is_int_type(enum_field_types t) { is_int_type(enum_field_types t) {
switch (t) { switch (t) {
......
...@@ -3,10 +3,11 @@ enum { ...@@ -3,10 +3,11 @@ enum {
UPDATE_OP_COL_ADD_OR_DROP = 0, UPDATE_OP_COL_ADD_OR_DROP = 0,
UPDATE_OP_EXPAND_VARCHAR_OFFSETS = 1, UPDATE_OP_EXPAND_VARCHAR_OFFSETS = 1,
UPDATE_OP_EXPAND_INT = 2, UPDATE_OP_EXPAND_INT = 2,
UPDATE_OP_EXPAND_CHAR = 3, UPDATE_OP_EXPAND_UINT = 3,
UPDATE_OP_EXPAND_BINARY = 4, UPDATE_OP_EXPAND_CHAR = 4,
UPDATE_OP_ADD_INT = 5, UPDATE_OP_EXPAND_BINARY = 5,
UPDATE_OP_SUB_INT = 6, UPDATE_OP_ADD_INT = 6,
UPDATE_OP_SUB_INT = 7,
}; };
#define UP_COL_ADD_OR_DROP UPDATE_OP_COL_ADD_OR_DROP #define UP_COL_ADD_OR_DROP UPDATE_OP_COL_ADD_OR_DROP
...@@ -62,13 +63,11 @@ enum { ...@@ -62,13 +63,11 @@ enum {
// offset_start 4 starting offset of the variable length field offsets // offset_start 4 starting offset of the variable length field offsets
// offset end 4 ending 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 offset 4
// old length 4 // old length 4
// new offset 4 // new offset 4
// new length 4 // new length 4
// if operation == UPDATE_OP_EXPAND_INT
// is unsigned 1
// operation 1 == UPDATE_OP_INT_ADD or UPDATE_OP_INT_SUB // operation 1 == UPDATE_OP_INT_ADD or UPDATE_OP_INT_SUB
// offset 4 starting offset of the int type field // offset 4 starting offset of the int type field
...@@ -719,9 +718,8 @@ tokudb_expand_field( ...@@ -719,9 +718,8 @@ tokudb_expand_field(
uchar *extra_pos = (uchar *)extra->data; uchar *extra_pos = (uchar *)extra->data;
uchar operation = extra_pos[0]; uchar operation = extra_pos[0];
assert(operation == UPDATE_OP_EXPAND_INT || assert(operation == UPDATE_OP_EXPAND_INT || operation == UPDATE_OP_EXPAND_UINT ||
operation == UPDATE_OP_EXPAND_CHAR || operation == UPDATE_OP_EXPAND_CHAR || operation == UPDATE_OP_EXPAND_BINARY);
operation == UPDATE_OP_EXPAND_BINARY);
extra_pos += sizeof operation; extra_pos += sizeof operation;
uint32_t old_offset; uint32_t old_offset;
...@@ -740,22 +738,7 @@ tokudb_expand_field( ...@@ -740,22 +738,7 @@ tokudb_expand_field(
memcpy(&new_length, extra_pos, sizeof new_length); memcpy(&new_length, extra_pos, sizeof 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(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(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(new_length >= old_length); // expand only
assert(old_offset + old_length <= old_val->size); // old field within the old val assert(old_offset + old_length <= old_val->size); // old field within the old val
...@@ -783,14 +766,16 @@ tokudb_expand_field( ...@@ -783,14 +766,16 @@ tokudb_expand_field(
// read the old field, expand it, write to the new offset // read the old field, expand it, write to the new offset
switch (operation) { switch (operation) {
case UPDATE_OP_EXPAND_INT: 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); memset(new_val_ptr, 0, new_length);
} else { memcpy(new_val_ptr, old_val_ptr, old_length);
if (old_val_ptr[old_length-1] & 0x80) // sign bit on? new_val_ptr += new_length;
memset(new_val_ptr, 0xff, new_length); // sign extend old_val_ptr += old_length;
else break;
memset(new_val_ptr, 0, new_length); case UPDATE_OP_EXPAND_UINT:
} memset(new_val_ptr, 0, new_length);
memcpy(new_val_ptr, old_val_ptr, old_length); memcpy(new_val_ptr, old_val_ptr, old_length);
new_val_ptr += new_length; new_val_ptr += new_length;
old_val_ptr += old_length; old_val_ptr += old_length;
...@@ -854,6 +839,7 @@ tokudb_update_fun( ...@@ -854,6 +839,7 @@ tokudb_update_fun(
error = tokudb_expand_varchar_offsets(db, key, old_val, extra, set_val, set_extra); error = tokudb_expand_varchar_offsets(db, key, old_val, extra, set_val, set_extra);
break; break;
case UPDATE_OP_EXPAND_INT: case UPDATE_OP_EXPAND_INT:
case UPDATE_OP_EXPAND_UINT:
case UPDATE_OP_EXPAND_CHAR: case UPDATE_OP_EXPAND_CHAR:
case UPDATE_OP_EXPAND_BINARY: case UPDATE_OP_EXPAND_BINARY:
error = tokudb_expand_field(db, key, old_val, extra, set_val, set_extra); 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