diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c index 6cefdb60956..cad51c224e2 100644 --- a/innobase/buf/buf0flu.c +++ b/innobase/buf/buf0flu.c @@ -412,6 +412,9 @@ buf_flush_write_block_low( /*======================*/ buf_block_t* block) /* in: buffer block to write */ { +#ifdef UNIV_LOG_DEBUG + static ibool univ_log_debug_warned; +#endif /* UNIV_LOG_DEBUG */ ut_a(block->state == BUF_BLOCK_FILE_PAGE); #ifdef UNIV_IBUF_DEBUG @@ -420,8 +423,13 @@ buf_flush_write_block_low( ut_ad(!ut_dulint_is_zero(block->newest_modification)); #ifdef UNIV_LOG_DEBUG - fputs("Warning: cannot force log to disk in the log debug version!\n", - stderr); + if (!univ_log_debug_warned) { + univ_log_debug_warned = TRUE; + fputs( + "Warning: cannot force log to disk if UNIV_LOG_DEBUG is defined!\n" + "Crash recovery will not work!\n", + stderr); + } #else /* Force the log to the disk before writing the modified block */ log_write_up_to(block->newest_modification, LOG_WAIT_ALL_GROUPS, TRUE); diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c index 7e57efcf9e1..e5b0300239a 100644 --- a/innobase/log/log0recv.c +++ b/innobase/log/log0recv.c @@ -628,6 +628,9 @@ log_block_checksum_is_ok_or_old_format( format of InnoDB version < 3.23.52 */ byte* block) /* in: pointer to a log block */ { +#ifdef UNIV_LOG_DEBUG + return(TRUE); +#endif /* UNIV_LOG_DEBUG */ if (log_block_calc_checksum(block) == log_block_get_checksum(block)) { return(TRUE); diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 556c80c948d..dfe7f070637 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -2284,7 +2284,6 @@ row_drop_table_for_mysql( "COMMIT WORK;\n" "END;\n"; - ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_a(name != NULL); if (srv_created_new_raw) { diff --git a/myisam/mi_key.c b/myisam/mi_key.c index d19a3130a86..a9b5a8b279f 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -32,6 +32,9 @@ static int _mi_put_key_in_record(MI_INFO *info,uint keynr,byte *record); ** Ret: Length of key */ +#define my_charpos(cs, b, e, num)\ + (cs)->cset->charpos((cs), (const char*) (b), (const char *)(e), (num)) + uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, const byte *record, my_off_t filepos) { @@ -57,6 +60,8 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, { enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type; uint length=keyseg->length; + uint char_length; + CHARSET_INFO *cs; if (keyseg->null_bit) { @@ -68,6 +73,15 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, *key++=1; /* Not NULL */ } + char_length= (cs= keyseg->charset) && (cs->mbmaxlen > 1) ? + length / cs->mbmaxlen : 0; + + if (info->s->keyinfo[keynr].flag & HA_FULLTEXT) + { + /* Ask Serg to make a better fix */ + char_length= 0; + } + pos= (byte*) record+keyseg->start; if (keyseg->flag & HA_SPACE_PACK) { @@ -83,6 +97,11 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, pos++; } length=(uint) (end-pos); + if (char_length && length > char_length) + { + char_length= my_charpos(cs, pos, pos+length, char_length); + set_if_smaller(length, char_length); + } store_key_length_inc(key,length); memcpy((byte*) key,(byte*) pos,(size_t) length); key+=length; @@ -94,13 +113,26 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, pos+=2; /* Skip VARCHAR length */ set_if_smaller(length,tmp_length); store_key_length_inc(key,length); + memcpy((byte*) key, pos, length); + key+= length; + continue; } else if (keyseg->flag & HA_BLOB_PART) { uint tmp_length=_mi_calc_blob_length(keyseg->bit_start,pos); memcpy_fixed((byte*) &pos,pos+keyseg->bit_start,sizeof(char*)); set_if_smaller(length,tmp_length); +#if NOT_YET_BLOB_PART + if (char_length && length > char_length) + { + char_length= my_charpos(cs, pos, pos+length, char_length); + set_if_smaller(length, char_length); + } +#endif store_key_length_inc(key,length); + memcpy((byte*) key, pos, length); + key+= length; + continue; } else if (keyseg->flag & HA_SWAP_KEY) { /* Numerical column */ @@ -136,6 +168,13 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, } continue; } +#ifdef NOT_YET_FIXED_LENGTH_KEY + if (char_length && length > char_length) + { + char_length= my_charpos(cs, pos, pos+length, char_length); + set_if_smaller(length, char_length); + } +#endif memcpy((byte*) key, pos, length); key+= length; } diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index b8ca99fe8f1..4d1b5d54bda 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -243,3 +243,36 @@ select 'zвасяz' rlike '[[:<:]]вася[[:>:]]'; CREATE TABLE t1 (a enum ('Y', 'N') DEFAULT 'N' COLLATE utf8_unicode_ci); ALTER TABLE t1 ADD COLUMN b CHAR(20); DROP TABLE t1; +create table t1 (c varchar(30) character set utf8, unique(c(10))); +insert into t1 values ('1'),('2'),('3'),('x'),('y'),('z'); +insert into t1 values ('aaaaaaaaaa'); +insert into t1 values ('aaaaaaaaaaa'); +ERROR 23000: Duplicate entry 'aaaaaaaaaaa' for key 1 +insert into t1 values ('aaaaaaaaaaaa'); +ERROR 23000: Duplicate entry 'aaaaaaaaaaaa' for key 1 +insert into t1 values (repeat('b',20)); +select c c1 from t1 where c='1'; +c1 +1 +select c c2 from t1 where c='2'; +c2 +2 +select c c3 from t1 where c='3'; +c3 +3 +select c cx from t1 where c='x'; +cx +x +select c cy from t1 where c='y'; +cy +y +select c cz from t1 where c='z'; +cz +z +select c ca10 from t1 where c='aaaaaaaaaa'; +ca10 +aaaaaaaaaa +select c cb20 from t1 where c=repeat('b',20); +cb20 +bbbbbbbbbbbbbbbbbbbb +drop table t1; diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index e07ee4f0add..345832387bd 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -673,3 +673,6 @@ c1 c2 2147483647 4294967295 -2147483648 0 drop table t1; +select left(1234, 3) + 0; +left(1234, 3) + 0 +123 diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 07baee1b3bd..4e130440a24 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -165,3 +165,25 @@ select 'zвасяz' rlike '[[:<:]]вася[[:>:]]'; CREATE TABLE t1 (a enum ('Y', 'N') DEFAULT 'N' COLLATE utf8_unicode_ci); ALTER TABLE t1 ADD COLUMN b CHAR(20); DROP TABLE t1; + +# +# Bug 4521: unique key prefix interacts poorly with utf8 +# Check keys with prefix compression +# +create table t1 (c varchar(30) character set utf8, unique(c(10))); +insert into t1 values ('1'),('2'),('3'),('x'),('y'),('z'); +insert into t1 values ('aaaaaaaaaa'); +--error 1062 +insert into t1 values ('aaaaaaaaaaa'); +--error 1062 +insert into t1 values ('aaaaaaaaaaaa'); +insert into t1 values (repeat('b',20)); +select c c1 from t1 where c='1'; +select c c2 from t1 where c='2'; +select c c3 from t1 where c='3'; +select c cx from t1 where c='x'; +select c cy from t1 where c='y'; +select c cz from t1 where c='z'; +select c ca10 from t1 where c='aaaaaaaaaa'; +select c cb20 from t1 where c=repeat('b',20); +drop table t1; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 61d0326f7dd..e7852df40b3 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -402,3 +402,9 @@ insert into t1 values ('-21474836461','-21474836461'); show warnings; select * from t1; drop table t1; + +# +# Bug #4878: LEFT() in integer/float context +# + +select left(1234, 3) + 0; diff --git a/mysql-test/t/grant_cache.test b/mysql-test/t/grant_cache.test index a82cd732802..e5bde977bb7 100644 --- a/mysql-test/t/grant_cache.test +++ b/mysql-test/t/grant_cache.test @@ -67,7 +67,8 @@ show status like "Qcache_queries_in_cache"; show status like "Qcache_hits"; show status like "Qcache_not_cached"; -connect (unkuser,localhost,,,,$MASTER_MYPORT,master.sock); +# Don't use '' as user because it will pick Unix login +connect (unkuser,localhost,unkuser,,,$MASTER_MYPORT,master.sock); connection unkuser; show grants for current_user(); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index d3493e1fad1..995627766c0 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -984,7 +984,10 @@ String *Item_func_left::val_str(String *str) return &my_empty_string; if (res->length() <= (uint) length) return res; - str_value.set(*res, 0, res->charpos(length)); + if (&str_value == res) + str_value.length(res->charpos(length)); + else + str_value.set(*res, 0, res->charpos(length)); return &str_value; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c81a888d2e9..48a2e1fbc71 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2535,7 +2535,8 @@ server."); if (opt_error_log) { if (!log_error_file_ptr[0]) - fn_format(log_error_file, glob_hostname, mysql_data_home, ".err", 0); + fn_format(log_error_file, glob_hostname, mysql_data_home, ".err", + MY_REPLACE_EXT); /* replace '.' by '.err', bug#4997 */ else fn_format(log_error_file, log_error_file_ptr, mysql_data_home, ".err", MY_UNPACK_FILENAME | MY_SAFE_PATH); diff --git a/sql/slave.cc b/sql/slave.cc index 7e46fb81053..0fe525d766f 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1236,6 +1236,12 @@ not always make sense; please check the manual before using it)."; /* Check that the master's global character_set_server and ours are the same. Not fatal if query fails (old master?). + Note that we don't check for equality of global character_set_client and + collation_connection (neither do we prevent their setting in + set_var.cc). That's because from what I (Guilhem) have tested, the global + values of these 2 are never used (new connections don't use them). + We don't test equality of global collation_database either as it's is + going to be deprecated (made read-only) in 4.1 very soon. */ if (!mysql_real_query(mysql, "SELECT @@GLOBAL.COLLATION_SERVER", 32) && (master_res= mysql_store_result(mysql))) diff --git a/sql/sql_string.h b/sql/sql_string.h index 01329c45a98..0179b3ebadc 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -98,6 +98,7 @@ public: void set(String &str,uint32 offset,uint32 arg_length) { + DBUG_ASSERT(&str != this); free(); Ptr=(char*) str.ptr()+offset; str_length=arg_length; alloced=0; if (str.Alloced_length)