diff options
author | aivanov@mysql.com <> | 2006-01-16 14:32:43 +0300 |
---|---|---|
committer | aivanov@mysql.com <> | 2006-01-16 14:32:43 +0300 |
commit | 708f9b3ceb0eb4e19cb83e53c81dee85bb72aadb (patch) | |
tree | 42a4966dcc1d1565033773730d0782e22ce4570b /sql/ha_innodb.cc | |
parent | 9ae629e80d75b3fb0b8e3a8cfdabe5e0ccd5d9d7 (diff) | |
download | mariadb-git-708f9b3ceb0eb4e19cb83e53c81dee85bb72aadb.tar.gz |
Changes from the innodb-5.0-ss115 snapshot.
Fixed bugs:
BUG#15991: "innodb-file-per-table + symlink database + rename = crash"
BUG#15650: "DELETE with LEFT JOIN crashes server"
BUG#15308: "Problem of Order with Enum Column in Primary Key"
BUG#14189: "VARBINARY and BINARY variables: trailing space ignored"
Diffstat (limited to 'sql/ha_innodb.cc')
-rw-r--r-- | sql/ha_innodb.cc | 164 |
1 files changed, 102 insertions, 62 deletions
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 744bd242fca..4ae0bb52d17 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1218,7 +1218,7 @@ innobase_init(void) "innobase_buffer_pool_size can't be over 4GB" " on 32-bit systems"); - goto error; + DBUG_RETURN(0); } if (innobase_log_file_size > UINT_MAX32) { @@ -1226,7 +1226,7 @@ innobase_init(void) "innobase_log_file_size can't be over 4GB" " on 32-bit systems"); - goto error; + DBUG_RETURN(0); } } @@ -1391,6 +1391,7 @@ innobase_init(void) ut_a(DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL == my_charset_latin1.number); + ut_a(DATA_MYSQL_BINARY_CHARSET_COLL == my_charset_bin.number); /* Store the latin1_swedish_ci character ordering table to InnoDB. For non-latin1_swedish_ci charsets we use the MySQL comparison functions, @@ -2847,8 +2848,6 @@ ha_innobase::store_key_val_for_row( char* buff_start = buff; enum_field_types mysql_type; Field* field; - ulint blob_len; - byte* blob_data; ibool is_null; DBUG_ENTER("store_key_val_for_row"); @@ -2903,14 +2902,18 @@ ha_innobase::store_key_val_for_row( ulint len; byte* data; ulint key_len; + ulint true_len; CHARSET_INFO* cs; int error=0; + key_len = key_part->length; + if (is_null) { - buff += key_part->length + 2; + buff += key_len + 2; continue; } + cs = field->charset(); lenlen = (ulint) (((Field_varstring*)field)->length_bytes); @@ -2920,32 +2923,33 @@ ha_innobase::store_key_val_for_row( + (ulint)get_field_offset(table, field)), lenlen); + true_len = len; + + /* For multi byte character sets we need to calculate + the true length of the key */ + + if (len > 0 && cs->mbmaxlen > 1) { + true_len = (ulint) cs->cset->well_formed_len(cs, + (const char *) data, + (const char *) data + len, + key_len / cs->mbmaxlen, + &error); + } + /* In a column prefix index, we may need to truncate the stored value: */ - - cs = key_part->field->charset(); - - if (cs->mbmaxlen > 1 && key_part->length > 0) { - key_len = (ulint) cs->cset->well_formed_len(cs, - (const char *) data, - (const char *) data + key_part->length, - key_part->length / cs->mbmaxlen, - &error); - } else { - key_len = key_part->length; - } - if (len > key_len) { - len = key_len; + if (true_len > key_len) { + true_len = key_len; } /* The length in a key value is always stored in 2 bytes */ - row_mysql_store_true_var_len((byte*)buff, len, 2); + row_mysql_store_true_var_len((byte*)buff, true_len, 2); buff += 2; - memcpy(buff, data, len); + memcpy(buff, data, true_len); /* Note that we always reserve the maximum possible length of the true VARCHAR in the key value, though @@ -2953,7 +2957,7 @@ ha_innobase::store_key_val_for_row( actual data. The rest of the space was reset to zero in the bzero() call above. */ - buff += key_part->length; + buff += key_len; } else if (mysql_type == FIELD_TYPE_TINY_BLOB || mysql_type == FIELD_TYPE_MEDIUM_BLOB @@ -2963,58 +2967,66 @@ ha_innobase::store_key_val_for_row( CHARSET_INFO* cs; ulint key_len; ulint len; + ulint true_len; int error=0; + ulint blob_len; + byte* blob_data; ut_a(key_part->key_part_flag & HA_PART_KEY_SEG); + key_len = key_part->length; + if (is_null) { - buff += key_part->length + 2; + buff += key_len + 2; continue; } + cs = field->charset(); + blob_data = row_mysql_read_blob_ref(&blob_len, (byte*) (record + (ulint)get_field_offset(table, field)), (ulint) field->pack_length()); + true_len = blob_len; + ut_a(get_field_offset(table, field) == key_part->offset); + /* For multi byte character sets we need to calculate + the true length of the key */ + + if (blob_len > 0 && cs->mbmaxlen > 1) { + true_len = (ulint) cs->cset->well_formed_len(cs, + (const char *) blob_data, + (const char *) blob_data + + blob_len, + key_len / cs->mbmaxlen, + &error); + } + /* All indexes on BLOB and TEXT are column prefix indexes, and we may need to truncate the data to be stored in the key value: */ - cs = key_part->field->charset(); - - if (cs->mbmaxlen > 1 && key_part->length > 0) { - key_len = (ulint) cs->cset->well_formed_len(cs, - (const char *) blob_data, - (const char *) blob_data - + key_part->length, - key_part->length / cs->mbmaxlen, - &error); - } else { - key_len = key_part->length; - } - - if (blob_len > key_len) { - blob_len = key_len; + if (true_len > key_len) { + true_len = key_len; } /* MySQL reserves 2 bytes for the length and the storage of the number is little-endian */ innobase_write_to_2_little_endian( - (byte*)buff, (ulint)blob_len); + (byte*)buff, true_len); buff += 2; - memcpy(buff, blob_data, blob_len); + memcpy(buff, blob_data, true_len); /* Note that we always reserve the maximum possible length of the BLOB prefix in the key value. */ - buff += key_part->length; + buff += key_len; } else { /* Here we handle all other data types except the true VARCHAR, BLOB and TEXT. Note that the column @@ -3022,38 +3034,64 @@ ha_innobase::store_key_val_for_row( index. */ CHARSET_INFO* cs; - ulint len; + ulint true_len; + ulint key_len; const mysql_byte* src_start; int error=0; + enum_field_types real_type; + + key_len = key_part->length; if (is_null) { - buff += key_part->length; + buff += key_len; continue; } - cs = key_part->field->charset(); src_start = record + key_part->offset; + real_type = field->real_type(); + true_len = key_len; - if (key_part->length > 0 && cs->mbmaxlen > 1) { - len = (ulint) cs->cset->well_formed_len(cs, - (const char *) src_start, - (const char *) src_start + key_part->length, - key_part->length / cs->mbmaxlen, - &error); - } else { - len = key_part->length; + /* Character set for the field is defined only + to fields whose type is string and real field + type is not enum or set. For these fields check + if character set is multi byte. */ + + if (real_type != FIELD_TYPE_ENUM + && real_type != FIELD_TYPE_SET + && ( mysql_type == MYSQL_TYPE_VAR_STRING + || mysql_type == MYSQL_TYPE_STRING)) { + + cs = field->charset(); + + /* For multi byte character sets we need to + calculate the true length of the key */ + + if (key_len > 0 && cs->mbmaxlen > 1) { + + true_len = (ulint) + cs->cset->well_formed_len(cs, + (const char *)src_start, + (const char *)src_start + + key_len, + key_len / cs->mbmaxlen, + &error); + } } - memcpy(buff, src_start, len); - buff+=len; + memcpy(buff, src_start, true_len); + buff += true_len; - /* Pad the unused space with spaces */ + /* Pad the unused space with spaces. Note that no + padding is ever needed for UCS-2 because in MySQL, + all UCS2 characters are 2 bytes, as MySQL does not + support surrogate pairs, which are needed to represent + characters in the range U+10000 to U+10FFFF. */ - if (len < key_part->length) { - len = key_part->length - len; - memset(buff, ' ', len); - buff+=len; + if (true_len < key_len) { + ulint pad_len = key_len - true_len; + memset(buff, ' ', pad_len); + buff += pad_len; } } } @@ -3770,9 +3808,8 @@ ha_innobase::delete_row( } /************************************************************************** -Removes a new lock set on a row. This can be called after a row has been read -in the processing of an UPDATE or a DELETE query, if the option -innodb_locks_unsafe_for_binlog is set. */ +Removes a new lock set on a row. This method does nothing unless the +option innodb_locks_unsafe_for_binlog is set.*/ void ha_innobase::unlock_row(void) @@ -3794,6 +3831,9 @@ ha_innobase::unlock_row(void) if (srv_locks_unsafe_for_binlog) { row_unlock_for_mysql(prebuilt, FALSE); } + + DBUG_VOID_RETURN; + } /********************************************************************** |