diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 18 | ||||
-rw-r--r-- | sql/ha_innodb.cc | 45 | ||||
-rw-r--r-- | sql/sql_cache.cc | 74 |
3 files changed, 71 insertions, 66 deletions
diff --git a/sql/field.cc b/sql/field.cc index eaa1ca2bcca..ec3bd72878d 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2970,6 +2970,14 @@ timestamp_auto_set_type Field_timestamp::get_auto_set_type() const return TIMESTAMP_AUTO_SET_ON_INSERT; case TIMESTAMP_UN_FIELD: return TIMESTAMP_AUTO_SET_ON_UPDATE; + case TIMESTAMP_OLD_FIELD: + /* + Altough we can have several such columns in legacy tables this + function should be called only for first of them (i.e. the one + having auto-set property). + */ + DBUG_ASSERT(table->timestamp_field == this); + /* Fall-through */ case TIMESTAMP_DNUN_FIELD: return TIMESTAMP_AUTO_SET_ON_BOTH; default: @@ -5077,6 +5085,11 @@ void Field_blob::get_key_image(char *buff,uint length, } #endif /*HAVE_SPATIAL*/ + get_ptr(&blob); + uint char_length= length / cs->mbmaxlen; + char_length= my_charpos(cs, blob, blob + length, char_length); + set_if_smaller(length, char_length); + if ((uint32) length > blob_length) { /* @@ -5087,7 +5100,6 @@ void Field_blob::get_key_image(char *buff,uint length, length=(uint) blob_length; } int2store(buff,length); - get_ptr(&blob); memcpy(buff+HA_KEY_BLOB_LENGTH, blob, length); } @@ -5103,6 +5115,10 @@ int Field_blob::key_cmp(const byte *key_ptr, uint max_key_length) char *blob1; uint blob_length=get_length(ptr); memcpy_fixed(&blob1,ptr+packlength,sizeof(char*)); + CHARSET_INFO *cs= charset(); + uint char_length= max_key_length / cs->mbmaxlen; + char_length= my_charpos(cs, blob1, blob1+blob_length, char_length); + set_if_smaller(blob_length, char_length); return Field_blob::cmp(blob1,min(blob_length, max_key_length), (char*) key_ptr+HA_KEY_BLOB_LENGTH, uint2korr(key_ptr)); diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 132bb835d82..f5da82a8a8c 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -3525,10 +3525,6 @@ create_index( prefix_len = 0; } - if (prefix_len >= DICT_MAX_COL_PREFIX_LEN) { - DBUG_RETURN(-1); - } - /* We assume all fields should be sorted in ascending order, hence the '0': */ @@ -5333,39 +5329,32 @@ innobase_get_at_most_n_mbchars( /* If the charset is multi-byte, then we must find the length of the first at most n chars in the string. If the string contains less characters than n, then we return the length to the end of the last - full character. */ + character. */ if (charset->mbmaxlen > 1) { -/* ulint right_value; */ - /* my_charpos() returns the byte length of the first n_chars - characters, or the end of the last full character */ + characters, or a value bigger than the length of str, if + there were not enough full characters in str. + + Why does the code below work: + Suppose that we are looking for n UTF-8 characters. + + 1) If the string is long enough, then the prefix contains at + least n complete UTF-8 characters + maybe some extra + characters + an incomplete UTF-8 character. No problem in + this case. The function returns the pointer to the + end of the nth character. + + 2) If the string is not long enough, then the string contains + the complete value of a column, that is, only complete UTF-8 + characters, and we can store in the column prefix index the + whole string. */ char_length = my_charpos(charset, str, str + data_len, n_chars); - - /*################################################*/ - /* TODO: my_charpos sometimes returns a non-sensical value - that is BIGGER than data_len: try to fix this bug partly with - these heuristics. This is NOT a complete bug fix! */ - if (char_length > data_len) { char_length = data_len; } - /*################################################*/ - -/* printf("data_len %lu, n_chars %lu, char_len %lu\n", - data_len, n_chars, char_length); - if (data_len < n_chars) { - right_value = data_len; - } else { - right_value = n_chars; - } - - if (right_value != char_length) { - printf("ERRRRRROOORRRRRRRRRRRR!!!!!!!!!\n"); - } -*/ } else { if (data_len < prefix_len) { char_length = data_len; diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 674452192f8..f69fb3085d3 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1953,55 +1953,55 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block, { ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) + ALIGN_SIZE(sizeof(Query_cache_result))); - ulong len= data_len + all_headers_len; - ulong align_len= ALIGN_SIZE(len); - DBUG_ENTER("Query_cache::allocate_data_chain"); - DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu", - data_len, all_headers_len)); - ulong min_size = (first_block_arg ? get_min_first_result_data_size(): get_min_append_result_data_size()); - *result_block = allocate_block(max(min_size, align_len), - min_result_data_size == 0, - all_headers_len + min_result_data_size, - 1); - my_bool success = (*result_block != 0); - if (success) + Query_cache_block *prev_block= NULL; + Query_cache_block *new_block; + DBUG_ENTER("Query_cache::allocate_data_chain"); + DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu", + data_len, all_headers_len)); + + do { - Query_cache_block *new_block= *result_block; + ulong len= data_len + all_headers_len; + ulong align_len= ALIGN_SIZE(len); + + if (!(new_block= allocate_block(max(min_size, align_len), + min_result_data_size == 0, + all_headers_len + min_result_data_size, + 1))) + { + DBUG_PRINT("warning", ("Can't allocate block for results")); + DBUG_RETURN(FALSE); + } + new_block->n_tables = 0; - new_block->used = 0; + new_block->used = min(len, new_block->length); new_block->type = Query_cache_block::RES_INCOMPLETE; new_block->next = new_block->prev = new_block; Query_cache_result *header = new_block->result(); header->parent(query_block); - if (new_block->length < len) - { - /* - We got less memory then we need (no big memory blocks) => - Continue to allocated more blocks until we got everything we need. - */ - Query_cache_block *next_block; - if ((success = allocate_data_chain(&next_block, - len - new_block->length, - query_block, first_block_arg))) - double_linked_list_join(new_block, next_block); - } - if (success) - { - new_block->used = min(len, new_block->length); - - DBUG_PRINT("qcache", ("Block len %lu used %lu", + DBUG_PRINT("qcache", ("Block len %lu used %lu", new_block->length, new_block->used)); - } + + if (prev_block) + double_linked_list_join(prev_block, new_block); else - DBUG_PRINT("warning", ("Can't allocate block for continue")); - } - else - DBUG_PRINT("warning", ("Can't allocate block for results")); - DBUG_RETURN(success); + *result_block= new_block; + if (new_block->length >= len) + break; + + /* + We got less memory then we need (no big memory blocks) => + Continue to allocated more blocks until we got everything we need. + */ + data_len= len - new_block->length; + prev_block= new_block; + } while(1); + + DBUG_RETURN(TRUE); } /***************************************************************************** |