summaryrefslogtreecommitdiff
path: root/sql/ha_innodb.cc
diff options
context:
space:
mode:
authoraivanov@mysql.com <>2006-01-16 14:32:43 +0300
committeraivanov@mysql.com <>2006-01-16 14:32:43 +0300
commit708f9b3ceb0eb4e19cb83e53c81dee85bb72aadb (patch)
tree42a4966dcc1d1565033773730d0782e22ce4570b /sql/ha_innodb.cc
parent9ae629e80d75b3fb0b8e3a8cfdabe5e0ccd5d9d7 (diff)
downloadmariadb-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.cc164
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;
+
}
/**********************************************************************