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

refs #5333 simplify column expansion messages

git-svn-id: file:///svn/mysql/tokudb-engine/tokudb-engine@47649 c7de825b-a66e-492c-adef-691d508d4ae1
parent 6372e1b6
......@@ -659,6 +659,7 @@ ha_tokudb::alter_table_expand_varchar_offsets(TABLE *altered_table, Alter_inplac
if (i == primary_key || table_share->key_info[i].flags & HA_CLUSTERING) {
uint32_t offset_start = table_share->null_bytes + share->kc_info.mcp_info[i].fixed_field_size;
uint32_t offset_end = offset_start + share->kc_info.mcp_info[i].len_of_offsets;
uint32_t number_of_offsets = offset_end - offset_start;
// make the expand varchar offsets message
DBT expand;
......@@ -673,12 +674,12 @@ ha_tokudb::alter_table_expand_varchar_offsets(TABLE *altered_table, Alter_inplac
expand_ptr[0] = UPDATE_OP_EXPAND_VARCHAR_OFFSETS;
expand_ptr += sizeof (uchar);
memcpy(expand_ptr, &number_of_offsets, sizeof number_of_offsets);
expand_ptr += sizeof number_of_offsets;
memcpy(expand_ptr, &offset_start, sizeof offset_start);
expand_ptr += sizeof offset_start;
memcpy(expand_ptr, &offset_end, sizeof offset_end);
expand_ptr += sizeof offset_end;
// and broadcast it into the tree
error = share->key_file[i]->update_broadcast(share->key_file[i], ctx->alter_txn, &expand, DB_IS_RESETTING_OP);
my_free(expand.data);
......@@ -720,8 +721,6 @@ change_varchar_length_is_supported(Field *old_field, Field *new_field, TABLE *ta
return false;
if (old_field->max_display_length() > new_field->max_display_length())
return false;
if (field_in_key(table, old_field))
return false;
if (ctx->table_kc_info->num_offset_bytes > ctx->altered_table_kc_info->num_offset_bytes)
return false; // something is wrong
if (ctx->table_kc_info->num_offset_bytes < ctx->altered_table_kc_info->num_offset_bytes)
......@@ -739,6 +738,10 @@ change_length_is_supported(TABLE *table, TABLE *altered_table, Alter_inplace_inf
uint i = ctx->changed_fields.at(ai);
Field *old_field = table->field[i];
Field *new_field = altered_table->field[i];
if (field_in_key(table, old_field))
return false;
if (field_in_key(altered_table, new_field))
return false;
// varchar(X) -> varchar(Y)
if (!change_varchar_length_is_supported(old_field, new_field, table, altered_table, ha_alter_info, ctx))
return false;
......@@ -840,7 +843,7 @@ ha_tokudb::alter_table_expand_one_column(TABLE *altered_table, Alter_inplace_inf
// make the expand int field message
DBT expand;
memset(&expand, 0, sizeof(expand));
expand.size = 1+4+4+4+4;
expand.size = 1+4+4+4;
expand.data = my_malloc(expand.size, MYF(MY_WME));
if (!expand.data) {
error = ENOMEM;
......@@ -850,19 +853,20 @@ 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->altered_table_kc_info, i, expand_field_num);
memcpy(expand_ptr, &old_offset, sizeof old_offset);
expand_ptr += sizeof old_offset;
uint32_t old_offset = field_offset(table_share->null_bytes, ctx->table_kc_info, i, expand_field_num);
uint32_t new_offset = field_offset(table_share->null_bytes, ctx->altered_table_kc_info, i, expand_field_num);
assert(old_offset <= new_offset);
// for the first altered field, old_offset == new_offset. for the subsequent altered fields, the new_offset
// should be used as it includes the length changes from the previous altered fields.
memcpy(expand_ptr, &new_offset, sizeof new_offset);
expand_ptr += sizeof new_offset;
uint32_t old_length = ctx->table_kc_info->field_lengths[expand_field_num];
assert(old_length == old_field->pack_length());
memcpy(expand_ptr, &old_length, sizeof old_length);
expand_ptr += sizeof old_length;
uint32_t new_offset = field_offset(table_share->null_bytes, ctx->altered_table_kc_info, i, expand_field_num);
memcpy(expand_ptr, &new_offset, sizeof new_offset);
expand_ptr += sizeof new_offset;
uint32_t new_length = ctx->altered_table_kc_info->field_lengths[expand_field_num];
assert(new_length == new_field->pack_length());
memcpy(expand_ptr, &new_length, sizeof new_length);
......@@ -905,8 +909,6 @@ change_fixed_length_is_supported(TABLE *table, TABLE *altered_table, Field *old_
// shrink is not supported
if (old_field->pack_length() > new_field->pack_length())
return false;
if (field_in_key(table, old_field))
return false;
ctx->expand_fixed_update_needed = true;
return true;
}
......@@ -945,6 +947,10 @@ change_type_is_supported(TABLE *table, TABLE *altered_table, Alter_inplace_info
uint i = ctx->changed_fields.at(ai);
Field *old_field = table->field[i];
Field *new_field = altered_table->field[i];
if (field_in_key(table, old_field))
return false;
if (field_in_key(altered_table, new_field))
return false;
if (!change_type_is_supported(old_field, new_field, table, altered_table, ha_alter_info, ctx))
return false;
}
......
// update operation codes. these codes get stuffed into update messages, so they can not change.
// Update operation codes. These codes get stuffed into update messages, so they can not change.
// The operations are currently stored in a single byte in the update message, so only 256 operations
// are supported. When we need more, we can use the last (255) code to indicate that the operation code
// is expanded beyond 1 byte.
enum {
UPDATE_OP_COL_ADD_OR_DROP = 0,
UPDATE_OP_EXPAND_VARCHAR_OFFSETS = 1,
......@@ -57,17 +60,20 @@ enum {
// at most, 4 0's
// So, upperbound is num_blobs(1+4+1+4) = num_columns*10
// The expand varchar offsets message is used to expand the size of an offset from 1 to 2 bytes.
// operation 1 == UPDATE_OP_EXPAND_VARCHAR_OFFSETS
// n_offsets 4 number of offsets
// 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/UINT, UPDATE_OP_EXPAND_CHAR, UPDATE_OP_EXPAND_BINARY
// old offset 4
// old length 4
// new offset 4
// new length 4
// These expand messages are used to expand the size of a fixed length field.
// The field type is encoded in the operation code.
// operation 1 == UPDATE_OP_EXPAND_INT, UPDATE_OP_EXPAND_UINT, UPDATE_OP_EXPAND_CHAR, UPDATE_OP_EXPAND_BINARY
// offset 4 starting offset of the field in the row's value
// old length 4 the old length of the field's value
// new length 4 the new length of the field's value
// operation 1 == UPDATE_OP_INT/UINT_ADD/SUB
// The int add and sub update messages are used to add or subtract a constant to or from an integer field.
// operation 1 == UPDATE_OP_INT_ADD, UPDATE_OP_INT_SUB, UPDATE_OP_UINT_ADD, UPDATE_OP_UINT_SUB
// offset 4 starting offset of the int type field
// length 4 length of the int type field
// value 4 value to add or subtract (common use case is increment or decrement by 1)
......@@ -631,21 +637,17 @@ tokudb_expand_varchar_offsets(
assert(operation == UPDATE_OP_EXPAND_VARCHAR_OFFSETS);
extra_pos += sizeof operation;
// decode number of offsets
uint32_t number_of_offsets;
memcpy(&number_of_offsets, extra_pos, sizeof number_of_offsets);
extra_pos += sizeof number_of_offsets;
// decode the offset start
uint32_t offset_start;
memcpy(&offset_start, extra_pos, sizeof offset_start);
extra_pos += sizeof offset_start;
// decode the offset end
uint32_t offset_end;
memcpy(&offset_end, extra_pos, sizeof offset_end);
extra_pos += sizeof offset_end;
// number of variable fields is the diff of the offset end and start
uint32_t number_of_offsets = offset_end - offset_start;
assert(extra_pos == (uchar *)extra->data + extra->size);
assert(offset_start < old_val->size);
assert(offset_start + number_of_offsets < old_val->size);
DBT new_val;
......@@ -719,26 +721,21 @@ tokudb_expand_field(
operation == UPDATE_OP_EXPAND_CHAR || operation == UPDATE_OP_EXPAND_BINARY);
extra_pos += sizeof operation;
uint32_t old_offset;
memcpy(&old_offset, extra_pos, sizeof old_offset);
extra_pos += sizeof old_offset;
uint32_t the_offset;
memcpy(&the_offset, extra_pos, sizeof the_offset);
extra_pos += sizeof the_offset;
uint32_t old_length;
memcpy(&old_length, extra_pos, sizeof old_length);
extra_pos += sizeof old_length;
uint32_t new_offset;
memcpy(&new_offset, extra_pos, sizeof new_offset);
extra_pos += sizeof new_offset;
uint32_t new_length;
memcpy(&new_length, extra_pos, sizeof new_length);
extra_pos += sizeof new_length;
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
assert(the_offset + old_length <= old_val->size); // old field within the old val
DBT new_val;
memset(&new_val, 0, sizeof(new_val));
......@@ -756,9 +753,9 @@ tokudb_expand_field(
new_val.data = new_val_ptr;
// copy up to the old offset
memcpy(new_val_ptr, old_val_ptr, old_offset);
new_val_ptr += new_offset;
old_val_ptr += old_offset;
memcpy(new_val_ptr, old_val_ptr, the_offset);
new_val_ptr += the_offset;
old_val_ptr += the_offset;
// read the old field, expand it, write to the new offset
switch (operation) {
......
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