summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/my_global.h3
-rw-r--r--innobase/srv/srv0start.c18
-rw-r--r--isam/create.c5
-rw-r--r--merge/mrg_create.c2
-rw-r--r--myisam/mi_create.c29
-rw-r--r--myisam/mi_open.c2
-rw-r--r--myisam/myisamdef.h1
-rw-r--r--myisammrg/myrg_create.c2
-rw-r--r--mysql-test/include/have_cp1250_ch.inc4
-rw-r--r--mysql-test/r/bigint.result39
-rw-r--r--mysql-test/r/ctype_collate.result4
-rw-r--r--mysql-test/r/ctype_cp1250_ch.result9
-rw-r--r--mysql-test/r/func_str.result62
-rw-r--r--mysql-test/r/func_system.result8
-rw-r--r--mysql-test/r/grant2.result16
-rw-r--r--mysql-test/r/have_cp1250_ch.require2
-rw-r--r--mysql-test/r/myisam.result18
-rw-r--r--mysql-test/r/mysqldump.result21
-rw-r--r--mysql-test/r/ps.result12
-rw-r--r--mysql-test/r/rpl_deadlock.result81
-rw-r--r--mysql-test/r/symlink.result12
-rw-r--r--mysql-test/r/type_blob.result2
-rw-r--r--mysql-test/t/bigint.test33
-rw-r--r--mysql-test/t/ctype_cp1250_ch.test12
-rw-r--r--mysql-test/t/func_system.test9
-rw-r--r--mysql-test/t/grant2.test14
-rw-r--r--mysql-test/t/myisam.test26
-rw-r--r--mysql-test/t/mysqldump.test9
-rw-r--r--mysql-test/t/ps.test11
-rw-r--r--mysql-test/t/rpl_deadlock-slave.opt1
-rw-r--r--mysql-test/t/rpl_deadlock.test107
-rw-r--r--mysql-test/t/symlink.test15
-rw-r--r--mysys/mf_tempfile.c8
-rw-r--r--mysys/my_symlink2.c7
-rw-r--r--ndb/include/ndbapi/NdbConnection.hpp3
-rw-r--r--ndb/src/kernel/blocks/dbtc/DbtcMain.cpp14
-rw-r--r--ndb/test/ndbapi/testNodeRestart.cpp71
-rw-r--r--ndb/test/run-test/daily-devel-tests.txt4
-rw-r--r--scripts/mysqlhotcopy.sh15
-rw-r--r--sql/ha_myisam.cc18
-rw-r--r--sql/item.cc10
-rw-r--r--sql/item.h19
-rw-r--r--sql/item_create.cc2
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/item_strfunc.cc17
-rw-r--r--sql/item_strfunc.h16
-rw-r--r--sql/mysql_priv.h4
-rw-r--r--sql/mysqld.cc23
-rw-r--r--sql/set_var.cc4
-rw-r--r--sql/share/english/errmsg.txt2
-rw-r--r--sql/slave.cc57
-rw-r--r--sql/slave.h4
-rw-r--r--sql/sql_acl.cc42
-rw-r--r--sql/sql_udf.cc105
-rw-r--r--sql/sql_union.cc30
-rw-r--r--sql/table.cc6
-rw-r--r--strings/ctype-win1250ch.c2
57 files changed, 867 insertions, 207 deletions
diff --git a/include/my_global.h b/include/my_global.h
index 7ca3d5e1e58..23cf0d54824 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -523,6 +523,9 @@ typedef SOCKET_SIZE_TYPE size_socket;
#ifndef O_SHORT_LIVED
#define O_SHORT_LIVED 0
#endif
+#ifndef O_NOFOLLOW
+#define O_NOFOLLOW 0
+#endif
/* #define USE_RECORD_LOCK */
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index fe05f07df21..44cf645f170 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -568,7 +568,14 @@ open_or_create_log_file(
files[i] = os_file_create(name, OS_FILE_CREATE, OS_FILE_NORMAL,
OS_LOG_FILE, &ret);
if (ret == FALSE) {
- if (os_file_get_last_error(FALSE) != OS_FILE_ALREADY_EXISTS) {
+ if (os_file_get_last_error(FALSE) != OS_FILE_ALREADY_EXISTS
+#ifdef UNIV_AIX
+ /* AIX 5.1 after security patch ML7 may have errno set
+ to 0 here, which causes our function to return 100;
+ work around that AIX problem */
+ && os_file_get_last_error(FALSE) != 100
+#endif
+ ) {
fprintf(stderr,
"InnoDB: Error in creating or opening %s\n", name);
@@ -728,7 +735,14 @@ open_or_create_data_files(
OS_FILE_NORMAL, OS_DATA_FILE, &ret);
if (ret == FALSE && os_file_get_last_error(FALSE) !=
- OS_FILE_ALREADY_EXISTS) {
+ OS_FILE_ALREADY_EXISTS
+#ifdef UNIV_AIX
+ /* AIX 5.1 after security patch ML7 may have
+ errno set to 0 here, which causes our function
+ to return 100; work around that AIX problem */
+ && os_file_get_last_error(FALSE) != 100
+#endif
+ ) {
fprintf(stderr,
"InnoDB: Error in creating or opening %s\n",
name);
diff --git a/isam/create.c b/isam/create.c
index 4c23f3edd11..204d3157d00 100644
--- a/isam/create.c
+++ b/isam/create.c
@@ -58,13 +58,14 @@ int nisam_create(const char *name,uint keys,N_KEYDEF *keyinfo,
base_pos=512; /* Enough for N_STATE_INFO */
bzero((byte*) &share,sizeof(share));
if ((file = my_create(fn_format(buff,name,"",N_NAME_IEXT,4),0,
- O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
+ O_RDWR | O_EXCL | O_NOFOLLOW,MYF(MY_WME))) < 0)
goto err;
errpos=1;
VOID(fn_format(buff,name,"",N_NAME_DEXT,2+4));
if (!(flags & HA_DONT_TOUCH_DATA))
{
- if ((dfile = my_create(buff,0,O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
+ if ((dfile = my_create(buff,0,O_RDWR | O_EXCL | O_NOFOLLOW,
+ MYF(MY_WME))) < 0)
goto err;
errpos=2;
}
diff --git a/merge/mrg_create.c b/merge/mrg_create.c
index d55a1421647..3508b7967f4 100644
--- a/merge/mrg_create.c
+++ b/merge/mrg_create.c
@@ -33,7 +33,7 @@ int mrg_create(const char *name, const char**table_names)
errpos=0;
if ((file = my_create(fn_format(buff,name,"",MRG_NAME_EXT,4),0,
- O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
+ O_RDWR | O_EXCL | O_NOFOLLOW,MYF(MY_WME))) < 0)
goto err;
errpos=1;
if (table_names)
diff --git a/myisam/mi_create.c b/myisam/mi_create.c
index f99a2c655d2..d363f3d5b67 100644
--- a/myisam/mi_create.c
+++ b/myisam/mi_create.c
@@ -39,7 +39,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
{
register uint i,j;
File dfile,file;
- int errpos,save_errno;
+ int errpos,save_errno, create_mode= O_RDWR | O_TRUNC;
myf create_flag;
uint fields,length,max_key_length,packed,pointer,real_length_diff,
key_length,info_length,key_segs,options,min_key_length_skip,
@@ -176,7 +176,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
min_pack_length+=varchar_length+2*varchar_count;
}
if (flags & HA_CREATE_TMP_TABLE)
+ {
options|= HA_OPTION_TMP_TABLE;
+ create_mode|= O_EXCL | O_NOFOLLOW;
+ }
if (flags & HA_CREATE_CHECKSUM || (options & HA_OPTION_CHECKSUM))
{
options|= HA_OPTION_CHECKSUM;
@@ -533,9 +536,22 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
create_flag=MY_DELETE_OLD;
}
- if ((file= my_create_with_symlink(linkname_ptr,
- filename,
- 0, O_RDWR | O_TRUNC,
+ /*
+ If a MRG_MyISAM table is in use, the mapped MyISAM tables are open,
+ but no entry is made in the table cache for them.
+ A TRUNCATE command checks for the table in the cache only and could
+ be fooled to believe, the table is not open.
+ Pull the emergency brake in this situation. (Bug #8306)
+ */
+ if (test_if_reopen(filename))
+ {
+ my_printf_error(0, "MyISAM table '%s' is in use "
+ "(most likely by a MERGE table). Try FLUSH TABLES.",
+ MYF(0), name + dirname_length(name));
+ goto err;
+ }
+
+ if ((file= my_create_with_symlink(linkname_ptr, filename, 0, create_mode,
MYF(MY_WME | create_flag))) < 0)
goto err;
errpos=1;
@@ -546,7 +562,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
if (share.base.raid_type)
{
(void) fn_format(filename,name,"",MI_NAME_DEXT,2+4);
- if ((dfile=my_raid_create(filename,0,O_RDWR | O_TRUNC,
+ if ((dfile=my_raid_create(filename, 0, create_mode,
share.base.raid_type,
share.base.raid_chunks,
share.base.raid_chunksize,
@@ -570,8 +586,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
create_flag=MY_DELETE_OLD;
}
if ((dfile=
- my_create_with_symlink(linkname_ptr, filename,
- 0,O_RDWR | O_TRUNC,
+ my_create_with_symlink(linkname_ptr, filename, 0, create_mode,
MYF(MY_WME | create_flag))) < 0)
goto err;
}
diff --git a/myisam/mi_open.c b/myisam/mi_open.c
index 2a327e4bd35..2c85a03c6f4 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -50,7 +50,7 @@ if (pos > end_pos) \
** In MySQL the server will handle version issues.
******************************************************************************/
-static MI_INFO *test_if_reopen(char *filename)
+MI_INFO *test_if_reopen(char *filename)
{
LIST *pos;
diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h
index 736ce3f3869..916932c9eb3 100644
--- a/myisam/myisamdef.h
+++ b/myisam/myisamdef.h
@@ -705,6 +705,7 @@ void mi_copy_status(void* to,void *from);
my_bool mi_check_status(void* param);
void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows);
+extern MI_INFO *test_if_reopen(char *filename);
my_bool check_table_is_closed(const char *name, const char *where);
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup);
int mi_open_keyfile(MYISAM_SHARE *share);
diff --git a/myisammrg/myrg_create.c b/myisammrg/myrg_create.c
index 5fc3c60ff32..7ddb7ecb3b9 100644
--- a/myisammrg/myrg_create.c
+++ b/myisammrg/myrg_create.c
@@ -34,7 +34,7 @@ int myrg_create(const char *name, const char **table_names,
errpos=0;
if ((file = my_create(fn_format(buff,name,"",MYRG_NAME_EXT,4),0,
- O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
+ O_RDWR | O_EXCL | O_NOFOLLOW,MYF(MY_WME))) < 0)
goto err;
errpos=1;
if (table_names)
diff --git a/mysql-test/include/have_cp1250_ch.inc b/mysql-test/include/have_cp1250_ch.inc
new file mode 100644
index 00000000000..eec5d69fbd6
--- /dev/null
+++ b/mysql-test/include/have_cp1250_ch.inc
@@ -0,0 +1,4 @@
+-- require r/have_cp1250_ch.require
+disable_query_log;
+show collation like "cp1250_czech_cs";
+enable_query_log;
diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result
index 4c70e72bdfb..eb3d0da3f23 100644
--- a/mysql-test/r/bigint.result
+++ b/mysql-test/r/bigint.result
@@ -87,3 +87,42 @@ drop table t1;
SELECT '0x8000000000000001'+0;
'0x8000000000000001'+0
0
+create table t1 (
+value64 bigint unsigned not null,
+value32 integer not null,
+primary key(value64, value32)
+);
+create table t2 (
+value64 bigint unsigned not null,
+value32 integer not null,
+primary key(value64, value32)
+);
+insert into t1 values(17156792991891826145, 1);
+insert into t1 values( 9223372036854775807, 2);
+insert into t2 values(17156792991891826145, 3);
+insert into t2 values( 9223372036854775807, 4);
+select * from t1;
+value64 value32
+9223372036854775807 2
+17156792991891826145 1
+select * from t2;
+value64 value32
+9223372036854775807 4
+17156792991891826145 3
+select * from t1, t2 where t1.value64=17156792991891826145 and
+t2.value64=17156792991891826145;
+value64 value32 value64 value32
+17156792991891826145 1 17156792991891826145 3
+select * from t1, t2 where t1.value64=17156792991891826145 and
+t2.value64=t1.value64;
+value64 value32 value64 value32
+17156792991891826145 1 17156792991891826145 3
+select * from t1, t2 where t1.value64= 9223372036854775807 and
+t2.value64=9223372036854775807;
+value64 value32 value64 value32
+9223372036854775807 2 9223372036854775807 4
+select * from t1, t2 where t1.value64= 9223372036854775807 and
+t2.value64=t1.value64;
+value64 value32 value64 value32
+9223372036854775807 2 9223372036854775807 4
+drop table t1, t2;
diff --git a/mysql-test/r/ctype_collate.result b/mysql-test/r/ctype_collate.result
index d4a8beda185..bc77e9c2362 100644
--- a/mysql-test/r/ctype_collate.result
+++ b/mysql-test/r/ctype_collate.result
@@ -514,7 +514,7 @@ Variable_name Value
character_set_client latin1
SELECT charset('a'),collation('a'),coercibility('a'),'a'='A';
charset('a') collation('a') coercibility('a') 'a'='A'
-latin1 latin1_swedish_ci 3 1
+latin1 latin1_swedish_ci 4 1
explain extended SELECT charset('a'),collation('a'),coercibility('a'),'a'='A';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
@@ -525,7 +525,7 @@ SHOW VARIABLES LIKE 'collation_client';
Variable_name Value
SELECT charset('a'),collation('a'),coercibility('a'),'a'='A';
charset('a') collation('a') coercibility('a') 'a'='A'
-latin1 latin1_swedish_ci 3 1
+latin1 latin1_swedish_ci 4 1
SET CHARACTER SET 'DEFAULT';
ERROR 42000: Unknown character set: 'DEFAULT'
DROP TABLE t1;
diff --git a/mysql-test/r/ctype_cp1250_ch.result b/mysql-test/r/ctype_cp1250_ch.result
new file mode 100644
index 00000000000..62936b84caf
--- /dev/null
+++ b/mysql-test/r/ctype_cp1250_ch.result
@@ -0,0 +1,9 @@
+SHOW COLLATION LIKE 'cp1250_czech_cs';
+Collation Charset Id Default Compiled Sortlen
+cp1250_czech_cs cp1250 34 Yes 2
+CREATE TABLE t1 (a char(16)) character set cp1250 collate cp1250_czech_cs;
+INSERT INTO t1 VALUES ('');
+SELECT a, length(a), a='', a=' ', a=' ' FROM t1;
+a length(a) a='' a=' ' a=' '
+ 0 1 1 1
+DROP TABLE t1;
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index f238915d3b9..2ef2329444c 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -464,97 +464,97 @@ select _latin1'B' COLLATE latin1_general_ci in (_latin1'a',_latin1'b' COLLATE la
ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT), (latin1_swedish_ci,COERCIBLE), (latin1_bin,EXPLICIT) for operation ' IN '
select collation(bin(130)), coercibility(bin(130));
collation(bin(130)) coercibility(bin(130))
-latin1_swedish_ci 3
+latin1_swedish_ci 4
select collation(oct(130)), coercibility(oct(130));
collation(oct(130)) coercibility(oct(130))
-latin1_swedish_ci 3
+latin1_swedish_ci 4
select collation(conv(130,16,10)), coercibility(conv(130,16,10));
collation(conv(130,16,10)) coercibility(conv(130,16,10))
-latin1_swedish_ci 3
+latin1_swedish_ci 4
select collation(hex(130)), coercibility(hex(130));
collation(hex(130)) coercibility(hex(130))
-latin1_swedish_ci 3
+latin1_swedish_ci 4
select collation(char(130)), coercibility(hex(130));
collation(char(130)) coercibility(hex(130))
-latin1_swedish_ci 3
+latin1_swedish_ci 4
select collation(format(130,10)), coercibility(format(130,10));
collation(format(130,10)) coercibility(format(130,10))
-latin1_swedish_ci 3
+latin1_swedish_ci 4
select collation(lcase(_latin2'a')), coercibility(lcase(_latin2'a'));
collation(lcase(_latin2'a')) coercibility(lcase(_latin2'a'))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(ucase(_latin2'a')), coercibility(ucase(_latin2'a'));
collation(ucase(_latin2'a')) coercibility(ucase(_latin2'a'))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(left(_latin2'a',1)), coercibility(left(_latin2'a',1));
collation(left(_latin2'a',1)) coercibility(left(_latin2'a',1))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(right(_latin2'a',1)), coercibility(right(_latin2'a',1));
collation(right(_latin2'a',1)) coercibility(right(_latin2'a',1))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(substring(_latin2'a',1,1)), coercibility(substring(_latin2'a',1,1));
collation(substring(_latin2'a',1,1)) coercibility(substring(_latin2'a',1,1))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(concat(_latin2'a',_latin2'b')), coercibility(concat(_latin2'a',_latin2'b'));
collation(concat(_latin2'a',_latin2'b')) coercibility(concat(_latin2'a',_latin2'b'))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(lpad(_latin2'a',4,_latin2'b')), coercibility(lpad(_latin2'a',4,_latin2'b'));
collation(lpad(_latin2'a',4,_latin2'b')) coercibility(lpad(_latin2'a',4,_latin2'b'))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(rpad(_latin2'a',4,_latin2'b')), coercibility(rpad(_latin2'a',4,_latin2'b'));
collation(rpad(_latin2'a',4,_latin2'b')) coercibility(rpad(_latin2'a',4,_latin2'b'))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(concat_ws(_latin2'a',_latin2'b')), coercibility(concat_ws(_latin2'a',_latin2'b'));
collation(concat_ws(_latin2'a',_latin2'b')) coercibility(concat_ws(_latin2'a',_latin2'b'))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(make_set(255,_latin2'a',_latin2'b',_latin2'c')), coercibility(make_set(255,_latin2'a',_latin2'b',_latin2'c'));
collation(make_set(255,_latin2'a',_latin2'b',_latin2'c')) coercibility(make_set(255,_latin2'a',_latin2'b',_latin2'c'))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(export_set(255,_latin2'y',_latin2'n',_latin2' ')), coercibility(export_set(255,_latin2'y',_latin2'n',_latin2' '));
collation(export_set(255,_latin2'y',_latin2'n',_latin2' ')) coercibility(export_set(255,_latin2'y',_latin2'n',_latin2' '))
-binary 3
+binary 4
select collation(trim(_latin2' a ')), coercibility(trim(_latin2' a '));
collation(trim(_latin2' a ')) coercibility(trim(_latin2' a '))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(ltrim(_latin2' a ')), coercibility(ltrim(_latin2' a '));
collation(ltrim(_latin2' a ')) coercibility(ltrim(_latin2' a '))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(rtrim(_latin2' a ')), coercibility(rtrim(_latin2' a '));
collation(rtrim(_latin2' a ')) coercibility(rtrim(_latin2' a '))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(trim(LEADING _latin2' ' FROM _latin2'a')), coercibility(trim(LEADING _latin2'a' FROM _latin2'a'));
collation(trim(LEADING _latin2' ' FROM _latin2'a')) coercibility(trim(LEADING _latin2'a' FROM _latin2'a'))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(trim(TRAILING _latin2' ' FROM _latin2'a')), coercibility(trim(TRAILING _latin2'a' FROM _latin2'a'));
collation(trim(TRAILING _latin2' ' FROM _latin2'a')) coercibility(trim(TRAILING _latin2'a' FROM _latin2'a'))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(trim(BOTH _latin2' ' FROM _latin2'a')), coercibility(trim(BOTH _latin2'a' FROM _latin2'a'));
collation(trim(BOTH _latin2' ' FROM _latin2'a')) coercibility(trim(BOTH _latin2'a' FROM _latin2'a'))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(repeat(_latin2'a',10)), coercibility(repeat(_latin2'a',10));
collation(repeat(_latin2'a',10)) coercibility(repeat(_latin2'a',10))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(reverse(_latin2'ab')), coercibility(reverse(_latin2'ab'));
collation(reverse(_latin2'ab')) coercibility(reverse(_latin2'ab'))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(quote(_latin2'ab')), coercibility(quote(_latin2'ab'));
collation(quote(_latin2'ab')) coercibility(quote(_latin2'ab'))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(soundex(_latin2'ab')), coercibility(soundex(_latin2'ab'));
collation(soundex(_latin2'ab')) coercibility(soundex(_latin2'ab'))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(substring(_latin2'ab',1)), coercibility(substring(_latin2'ab',1));
collation(substring(_latin2'ab',1)) coercibility(substring(_latin2'ab',1))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(insert(_latin2'abcd',2,3,_latin2'ef')), coercibility(insert(_latin2'abcd',2,3,_latin2'ef'));
collation(insert(_latin2'abcd',2,3,_latin2'ef')) coercibility(insert(_latin2'abcd',2,3,_latin2'ef'))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(replace(_latin2'abcd',_latin2'b',_latin2'B')), coercibility(replace(_latin2'abcd',_latin2'b',_latin2'B'));
collation(replace(_latin2'abcd',_latin2'b',_latin2'B')) coercibility(replace(_latin2'abcd',_latin2'b',_latin2'B'))
-latin2_general_ci 3
+latin2_general_ci 4
select collation(encode('abcd','ab')), coercibility(encode('abcd','ab'));
collation(encode('abcd','ab')) coercibility(encode('abcd','ab'))
-binary 3
+binary 4
create table t1
select
bin(130),
diff --git a/mysql-test/r/func_system.result b/mysql-test/r/func_system.result
index d3db2cc5151..d0ac9d781a4 100644
--- a/mysql-test/r/func_system.result
+++ b/mysql-test/r/func_system.result
@@ -68,3 +68,11 @@ drop table t1;
select TRUE,FALSE,NULL;
TRUE FALSE NULL
1 0 NULL
+create table t1 (a char(10)) character set latin1;
+select * from t1 where a=version();
+a
+select * from t1 where a=database();
+a
+select * from t1 where a=user();
+a
+drop table t1;
diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result
index 6d8bdbaf8f9..8200d112709 100644
--- a/mysql-test/r/grant2.result
+++ b/mysql-test/r/grant2.result
@@ -63,3 +63,19 @@ delete from mysql.columns_priv where user like 'mysqltest\_%';
flush privileges;
drop database mysqltest;
use test;
+create database mysqltest_1;
+create table mysqltest_1.t1 (i int);
+insert into mysqltest_1.t1 values (1),(2),(3);
+GRANT ALL ON mysqltest_1.t1 TO mysqltest_1@'127.0.0.0/255.0.0.0';
+show grants for current_user();
+Grants for mysqltest_1@127.0.0.0/255.0.0.0
+GRANT USAGE ON *.* TO 'mysqltest_1'@'127.0.0.0/255.0.0.0'
+GRANT ALL PRIVILEGES ON `mysqltest_1`.`t1` TO 'mysqltest_1'@'127.0.0.0/255.0.0.0'
+select * from t1;
+i
+1
+2
+3
+REVOKE ALL ON mysqltest_1.t1 FROM mysqltest_1@'127.0.0.0/255.0.0.0';
+drop table mysqltest_1.t1;
+drop database mysqltest_1;
diff --git a/mysql-test/r/have_cp1250_ch.require b/mysql-test/r/have_cp1250_ch.require
new file mode 100644
index 00000000000..2eb834d97e2
--- /dev/null
+++ b/mysql-test/r/have_cp1250_ch.require
@@ -0,0 +1,2 @@
+Collation Charset Id Default Compiled Sortlen
+cp1250_czech_cs cp1250 34 Yes 2
diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result
index d155a14bb60..eaed7c620e3 100644
--- a/mysql-test/r/myisam.result
+++ b/mysql-test/r/myisam.result
@@ -555,3 +555,21 @@ select count(*) from t1 where a is null;
count(*)
2
drop table t1;
+create table t1 (c1 int, index(c1));
+create table t2 (c1 int, index(c1)) engine=merge union=(t1);
+insert into t1 values (1);
+flush tables;
+select * from t2;
+c1
+1
+flush tables;
+truncate table t1;
+insert into t1 values (1);
+flush tables;
+select * from t2;
+c1
+1
+truncate table t1;
+ERROR HY000: MyISAM table 't1' is in use (most likely by a MERGE table). Try FLUSH TABLES.
+insert into t1 values (1);
+drop table t1,t2;
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index f763a16836f..ca92c44c99c 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -441,27 +441,6 @@ CREATE TABLE `t1` (
/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
LOCK TABLES `t1` WRITE;
-INSERT INTO `t1` VALUES ('ÄÖÜß');
-UNLOCK TABLES;
-/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
-
-/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
-/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
-/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
-/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-
-/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
-/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
-/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */;
-/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-DROP TABLE IF EXISTS `t1`;
-CREATE TABLE `t1` (
- `a` char(10) default NULL
-) TYPE=MyISAM;
-
-
-/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
-LOCK TABLES `t1` WRITE;
INSERT INTO `t1` VALUES ('Ž™šá');
UNLOCK TABLES;
/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 4e1e75f1b33..89c369a51e8 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -482,3 +482,15 @@ execute stmt;
pnum
deallocate prepare stmt;
drop table t1, t2;
+prepare stmt from "SELECT SQL_CALC_FOUND_ROWS 'foo' UNION SELECT 'bar' LIMIT 0";
+execute stmt;
+foo
+SELECT FOUND_ROWS();
+FOUND_ROWS()
+2
+execute stmt;
+foo
+SELECT FOUND_ROWS();
+FOUND_ROWS()
+2
+deallocate prepare stmt;
diff --git a/mysql-test/r/rpl_deadlock.result b/mysql-test/r/rpl_deadlock.result
new file mode 100644
index 00000000000..366d18f3e05
--- /dev/null
+++ b/mysql-test/r/rpl_deadlock.result
@@ -0,0 +1,81 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+create table t1 (a int not null, key(a)) engine=innodb;
+create table t2 (a int not null, key(a)) engine=innodb;
+create table t3 (a int) engine=innodb;
+create table t4 (a int) engine=innodb;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL default '0',
+ KEY `a` (`a`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) NOT NULL default '0',
+ KEY `a` (`a`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+stop slave;
+begin;
+insert into t3 select * from t2 for update;
+insert into t1 values(1);
+commit;
+begin;
+select * from t1 for update;
+a
+start slave;
+insert into t2 values(22);
+commit;
+select * from t1;
+a
+1
+select * from t2;
+a
+22
+show slave status;
+Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
+# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 13110 # # master-bin.000001 Yes Yes 0 0 13110 # None 0 No #
+stop slave;
+change master to master_log_pos=401;
+begin;
+select * from t2 for update;
+a
+22
+start slave;
+commit;
+select * from t1;
+a
+1
+1
+select * from t2;
+a
+22
+show slave status;
+Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
+# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 13110 # # master-bin.000001 Yes Yes 0 0 13110 # None 0 No #
+set global max_relay_log_size=0;
+stop slave;
+change master to master_log_pos=401;
+begin;
+select * from t2 for update;
+a
+22
+start slave;
+commit;
+select * from t1;
+a
+1
+1
+1
+select * from t2;
+a
+22
+show slave status;
+Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
+# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 13110 # # master-bin.000001 Yes Yes 0 0 13110 # None 0 No #
+drop table t1,t2;
diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result
index 08d75d8b562..26612ec81fd 100644
--- a/mysql-test/r/symlink.result
+++ b/mysql-test/r/symlink.result
@@ -84,3 +84,15 @@ t1 CREATE TABLE `t1` (
`b` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result
index 8a0c74b3ae5..12eb2902966 100644
--- a/mysql-test/r/type_blob.result
+++ b/mysql-test/r/type_blob.result
@@ -499,7 +499,7 @@ charset(load_file('../../std_data/words.dat')),
collation(load_file('../../std_data/words.dat')),
coercibility(load_file('../../std_data/words.dat'));
charset(load_file('../../std_data/words.dat')) collation(load_file('../../std_data/words.dat')) coercibility(load_file('../../std_data/words.dat'))
-binary binary 3
+binary binary 4
explain extended select
charset(load_file('../../std_data/words.dat')),
collation(load_file('../../std_data/words.dat')),
diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test
index c509a4113f4..a26b78254e7 100644
--- a/mysql-test/t/bigint.test
+++ b/mysql-test/t/bigint.test
@@ -71,3 +71,36 @@ drop table t1;
# atof() behaviour is different of different systems. to be fixed in 4.1
SELECT '0x8000000000000001'+0;
+# Test for BUG#8562: joins over BIGINT UNSIGNED value + constant propagation
+create table t1 (
+ value64 bigint unsigned not null,
+ value32 integer not null,
+ primary key(value64, value32)
+);
+
+create table t2 (
+ value64 bigint unsigned not null,
+ value32 integer not null,
+ primary key(value64, value32)
+);
+
+insert into t1 values(17156792991891826145, 1);
+insert into t1 values( 9223372036854775807, 2);
+insert into t2 values(17156792991891826145, 3);
+insert into t2 values( 9223372036854775807, 4);
+
+select * from t1;
+select * from t2;
+
+select * from t1, t2 where t1.value64=17156792991891826145 and
+t2.value64=17156792991891826145;
+select * from t1, t2 where t1.value64=17156792991891826145 and
+t2.value64=t1.value64;
+
+select * from t1, t2 where t1.value64= 9223372036854775807 and
+t2.value64=9223372036854775807;
+select * from t1, t2 where t1.value64= 9223372036854775807 and
+t2.value64=t1.value64;
+
+drop table t1, t2;
+
diff --git a/mysql-test/t/ctype_cp1250_ch.test b/mysql-test/t/ctype_cp1250_ch.test
new file mode 100644
index 00000000000..06aea7b9979
--- /dev/null
+++ b/mysql-test/t/ctype_cp1250_ch.test
@@ -0,0 +1,12 @@
+-- source include/have_cp1250_ch.inc
+
+SHOW COLLATION LIKE 'cp1250_czech_cs';
+
+#
+# Bugs: #8840: Empty string comparison and character set 'cp1250'
+#
+
+CREATE TABLE t1 (a char(16)) character set cp1250 collate cp1250_czech_cs;
+INSERT INTO t1 VALUES ('');
+SELECT a, length(a), a='', a=' ', a=' ' FROM t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/func_system.test b/mysql-test/t/func_system.test
index a05b80ca56b..7fff165e057 100644
--- a/mysql-test/t/func_system.test
+++ b/mysql-test/t/func_system.test
@@ -30,3 +30,12 @@ show create table t1;
drop table t1;
select TRUE,FALSE,NULL;
+
+#
+# Bug#8291 Illegal collation mix with USER() function
+#
+create table t1 (a char(10)) character set latin1;
+select * from t1 where a=version();
+select * from t1 where a=database();
+select * from t1 where a=user();
+drop table t1;
diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test
index 7060d35e9a4..8e1314aeace 100644
--- a/mysql-test/t/grant2.test
+++ b/mysql-test/t/grant2.test
@@ -89,3 +89,17 @@ flush privileges;
drop database mysqltest;
use test;
+# Bug #3309: Test IP addresses with netmask
+create database mysqltest_1;
+create table mysqltest_1.t1 (i int);
+insert into mysqltest_1.t1 values (1),(2),(3);
+GRANT ALL ON mysqltest_1.t1 TO mysqltest_1@'127.0.0.0/255.0.0.0';
+connect (n1,127.0.0.1,mysqltest_1,,mysqltest_1,$MASTER_MYPORT,$MASTER_MYSOCK);
+connection n1;
+show grants for current_user();
+select * from t1;
+disconnect n1;
+connection default;
+REVOKE ALL ON mysqltest_1.t1 FROM mysqltest_1@'127.0.0.0/255.0.0.0';
+drop table mysqltest_1.t1;
+drop database mysqltest_1;
diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test
index c8ed7910b76..0babd1f9401 100644
--- a/mysql-test/t/myisam.test
+++ b/mysql-test/t/myisam.test
@@ -524,3 +524,29 @@ explain select count(*) from t1 where a is null;
select count(*) from t1 where a is null;
drop table t1;
+#
+# Bug #8306: TRUNCATE leads to index corruption
+#
+create table t1 (c1 int, index(c1));
+create table t2 (c1 int, index(c1)) engine=merge union=(t1);
+insert into t1 values (1);
+# Close all tables.
+flush tables;
+# Open t2 and (implicitly) t1.
+select * from t2;
+# Truncate after flush works (unless another threads reopens t2 in between).
+flush tables;
+truncate table t1;
+insert into t1 values (1);
+# Close all tables.
+flush tables;
+# Open t2 and (implicitly) t1.
+select * from t2;
+# Truncate t1, wich was not recognized as open without the bugfix.
+# Now, it should fail with a table-in-use error message.
+--error 1105
+truncate table t1;
+# The insert used to fail on the crashed table.
+insert into t1 values (1);
+drop table t1,t2;
+
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index 255ae50a8ca..9ea5c1e58b5 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -148,7 +148,14 @@ drop database mysqldump_test_db;
CREATE TABLE t1 (a CHAR(10));
INSERT INTO t1 VALUES (_latin1 'ÄÖÜß');
--exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments test t1
---exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --compatible=mysql323 test t1
+#
+# Bug#8063: make test mysqldump [ fail ]
+# We cannot tes this command because its output depends
+# on --default-character-set incompiled into "mysqldump" program.
+# If the future we can move this command into a separate test with
+# checking that "mysqldump" is compiled with "latin1"
+#
+#--exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --compatible=mysql323 test t1
--exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --compatible=mysql323 --default-character-set=cp850 test t1
--exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --default-character-set=cp850 --compatible=mysql323 test t1
--exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --default-character-set=utf8 --compatible=mysql323 test t1
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index 92bf4ece4e3..b204e59267e 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -485,3 +485,14 @@ execute stmt;
deallocate prepare stmt;
drop table t1, t2;
+
+#
+# Bug #6089: FOUND_ROWS returns wrong values when no table/view is used
+#
+
+prepare stmt from "SELECT SQL_CALC_FOUND_ROWS 'foo' UNION SELECT 'bar' LIMIT 0";
+execute stmt;
+SELECT FOUND_ROWS();
+execute stmt;
+SELECT FOUND_ROWS();
+deallocate prepare stmt;
diff --git a/mysql-test/t/rpl_deadlock-slave.opt b/mysql-test/t/rpl_deadlock-slave.opt
new file mode 100644
index 00000000000..f4a8c640458
--- /dev/null
+++ b/mysql-test/t/rpl_deadlock-slave.opt
@@ -0,0 +1 @@
+--innodb --loose-innodb_lock_wait_timeout=4 --slave-transaction-retries=2 --max-relay-log-size=4096
diff --git a/mysql-test/t/rpl_deadlock.test b/mysql-test/t/rpl_deadlock.test
new file mode 100644
index 00000000000..82470e8ebd0
--- /dev/null
+++ b/mysql-test/t/rpl_deadlock.test
@@ -0,0 +1,107 @@
+# See if slave restarts the transaction after failing on an InnoDB deadlock error.
+
+# Note: testing what happens when too many retries is possible, but
+# needs large waits when running with --debug, so we don't do it.
+# The same way, this test may not test what is expected when run
+# under Valgrind, timings are too short then (with --valgrind I
+# (Guilhem) have seen the test manage to provoke lock wait timeout
+# error but not deadlock error; that is ok as code deals with the two
+# errors in exactly the same way.
+
+source include/have_innodb.inc;
+source include/master-slave.inc;
+
+connection master;
+create table t1 (a int not null, key(a)) engine=innodb;
+create table t2 (a int not null, key(a)) engine=innodb;
+create table t3 (a int) engine=innodb;
+create table t4 (a int) engine=innodb;
+sync_slave_with_master;
+
+show create table t1;
+show create table t2;
+stop slave;
+
+# 1) Test deadlock
+
+connection master;
+begin;
+# Let's keep BEGIN and the locked statement in two different relay logs.
+let $1=200;
+disable_query_log;
+while ($1)
+{
+ eval insert into t3 values( $1 );
+ dec $1;
+}
+enable_query_log;
+insert into t3 select * from t2 for update;
+insert into t1 values(1);
+commit;
+save_master_pos;
+
+connection slave;
+begin;
+# Let's make our transaction large so that it's slave who is chosen as
+# victim
+let $1=1000;
+disable_query_log;
+while ($1)
+{
+ eval insert into t4 values( $1 );
+ dec $1;
+}
+enable_query_log;
+select * from t1 for update;
+start slave;
+--sleep 3; # hope that slave is blocked now
+insert into t2 values(22); # provoke deadlock, slave should be victim
+commit;
+sync_with_master;
+select * from t1; # check that slave succeeded finally
+select * from t2;
+# check that no error is reported
+--replace_column 1 # 8 # 9 # 23 # 33 #
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+show slave status;
+
+# 2) Test lock wait timeout
+
+stop slave;
+change master to master_log_pos=401; # the BEGIN log event
+begin;
+select * from t2 for update; # hold lock
+start slave;
+--sleep 10; # slave should have blocked, and be retrying
+commit;
+sync_with_master;
+select * from t1; # check that slave succeeded finally
+select * from t2;
+# check that no error is reported
+--replace_column 1 # 8 # 9 # 23 # 33 #
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+show slave status;
+
+# Now we repeat 2), but with BEGIN in the same relay log as
+# COMMIT (to see if seeking into hot log is ok).
+
+set global max_relay_log_size=0;
+
+# This is really copy-paste of 2) of above
+stop slave;
+change master to master_log_pos=401;
+begin;
+select * from t2 for update;
+start slave;
+--sleep 10;
+commit;
+sync_with_master;
+select * from t1;
+select * from t2;
+--replace_column 1 # 8 # 9 # 23 # 33 #
+--replace_result $MASTER_MYPORT MASTER_MYPORT
+show slave status;
+
+connection master;
+drop table t1,t2;
+sync_slave_with_master;
diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test
index 78c9b68fde5..ddde5171200 100644
--- a/mysql-test/t/symlink.test
+++ b/mysql-test/t/symlink.test
@@ -115,3 +115,18 @@ eval alter table t1 index directory="$MYSQL_TEST_DIR/var/log";
enable_query_log;
show create table t1;
drop table t1;
+
+#
+# Test specifying DATA DIRECTORY that is the same as what would normally
+# have been chosen. (Bug #8707)
+#
+disable_query_log;
+eval create table t1 (i int) data directory = "$MYSQL_TEST_DIR/var/master-data/test/";
+enable_query_log;
+show create table t1;
+drop table t1;
+disable_query_log;
+eval create table t1 (i int) index directory = "$MYSQL_TEST_DIR/var/master-data/test/";
+enable_query_log;
+show create table t1;
+drop table t1;
diff --git a/mysys/mf_tempfile.c b/mysys/mf_tempfile.c
index af9ff0d6711..a15bda4da6d 100644
--- a/mysys/mf_tempfile.c
+++ b/mysys/mf_tempfile.c
@@ -70,7 +70,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix,
{
strmake(to,res,FN_REFLEN-1);
(*free)(res);
- file=my_create(to,0, mode, MyFlags);
+ file=my_create(to,0, mode | O_EXCL | O_NOFOLLOW, MyFlags);
}
environ=old_env;
}
@@ -81,7 +81,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix,
{
strmake(to,res,FN_REFLEN-1);
(*free)(res);
- file=my_create(to, 0, mode, MyFlags);
+ file=my_create(to, 0, mode | O_EXCL | O_NOFOLLOW, MyFlags);
}
#elif defined(HAVE_MKSTEMP) && !defined(__NETWARE__)
{
@@ -143,7 +143,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix,
strmake(to,res,FN_REFLEN-1);
(*free)(res);
file=my_create(to,0,
- (int) (O_RDWR | O_BINARY | O_TRUNC |
+ (int) (O_RDWR | O_BINARY | O_TRUNC | O_EXCL | O_NOFOLLOW |
O_TEMPORARY | O_SHORT_LIVED),
MYF(MY_WME));
@@ -186,7 +186,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix,
}
(void) strmov(end_pos,TMP_EXT);
file=my_create(to,0,
- (int) (O_RDWR | O_BINARY | O_TRUNC |
+ (int) (O_RDWR | O_BINARY | O_TRUNC | O_EXCL | O_NOFOLLOW |
O_TEMPORARY | O_SHORT_LIVED),
MYF(MY_WME));
}
diff --git a/mysys/my_symlink2.c b/mysys/my_symlink2.c
index 913f632fbb4..80dca7d56ac 100644
--- a/mysys/my_symlink2.c
+++ b/mysys/my_symlink2.c
@@ -32,6 +32,7 @@ File my_create_with_symlink(const char *linkname, const char *filename,
int tmp_errno;
/* Test if we should create a link */
int create_link;
+ char abs_linkname[FN_REFLEN];
DBUG_ENTER("my_create_with_symlink");
if (my_disable_symlinks)
@@ -42,7 +43,11 @@ File my_create_with_symlink(const char *linkname, const char *filename,
filename= linkname;
}
else
- create_link= (linkname && strcmp(linkname,filename));
+ {
+ if (linkname)
+ my_realpath(&abs_linkname, linkname, MYF(0));
+ create_link= (linkname && strcmp(abs_linkname,filename));
+ }
if (!(MyFlags & MY_DELETE_OLD))
{
diff --git a/ndb/include/ndbapi/NdbConnection.hpp b/ndb/include/ndbapi/NdbConnection.hpp
index 53830dd93c5..3a9f18665e9 100644
--- a/ndb/include/ndbapi/NdbConnection.hpp
+++ b/ndb/include/ndbapi/NdbConnection.hpp
@@ -448,6 +448,8 @@ public:
NdbScanOperation* getNdbScanOperation(const NdbDictionary::Table * table);
NdbIndexScanOperation* getNdbIndexScanOperation(const NdbDictionary::Index * index,
const NdbDictionary::Table * table);
+
+ Uint32 getConnectedNodeId(); // Get Connected node id
private:
/**
@@ -480,7 +482,6 @@ private:
*/
void setConnectedNodeId( Uint32 nodeId, Uint32 sequence);
- Uint32 getConnectedNodeId(); // Get Connected node id
void setMyBlockReference( int ); // Set my block refrerence
void setTC_ConnectPtr( Uint32 ); // Sets TC Connect pointer
int getTC_ConnectPtr(); // Gets TC Connect pointer
diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
index 97931041e2a..03a0590b6e2 100644
--- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
+++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
@@ -5193,7 +5193,8 @@ void Dbtc::execTC_COMMITREQ(Signal* signal)
const Uint32 transId1 = regApiPtr->transid[0];
const Uint32 transId2 = regApiPtr->transid[1];
Uint32 errorCode = 0;
-
+
+ regApiPtr->m_exec_flag = 1;
switch (regApiPtr->apiConnectstate) {
case CS_STARTED:
tcConnectptr.i = regApiPtr->firstTcConnect;
@@ -5922,11 +5923,17 @@ int Dbtc::releaseAndAbort(Signal* signal)
UintR TnoLoops = tcConnectptr.p->noOfNodes;
apiConnectptr.p->counter++;
+ bool prevAlive = false;
for (Uint32 Ti = 0; Ti < TnoLoops ; Ti++) {
localHostptr.i = tcConnectptr.p->tcNodedata[Ti];
ptrCheckGuard(localHostptr, chostFilesize, hostRecord);
if (localHostptr.p->hostStatus == HS_ALIVE) {
jam();
+ if (prevAlive) {
+ // if previous is alive, its LQH forwards abort to this node
+ jam();
+ continue;
+ }
/* ************< */
/* ABORT < */
/* ************< */
@@ -5936,15 +5943,16 @@ int Dbtc::releaseAndAbort(Signal* signal)
signal->theData[2] = apiConnectptr.p->transid[0];
signal->theData[3] = apiConnectptr.p->transid[1];
sendSignal(tblockref, GSN_ABORT, signal, 4, JBB);
- return 1;
+ prevAlive = true;
} else {
jam();
signal->theData[0] = tcConnectptr.i;
signal->theData[1] = apiConnectptr.p->transid[0];
signal->theData[2] = apiConnectptr.p->transid[1];
- signal->theData[3] = hostptr.i;
+ signal->theData[3] = localHostptr.i;
signal->theData[4] = ZFALSE;
sendSignal(cownref, GSN_ABORTED, signal, 5, JBB);
+ prevAlive = false;
}//if
}//for
return 1;
diff --git a/ndb/test/ndbapi/testNodeRestart.cpp b/ndb/test/ndbapi/testNodeRestart.cpp
index e844f227034..a50df91908c 100644
--- a/ndb/test/ndbapi/testNodeRestart.cpp
+++ b/ndb/test/ndbapi/testNodeRestart.cpp
@@ -344,6 +344,71 @@ err:
return NDBT_FAILED;
}
+int runLateCommit(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ NdbRestarter restarter;
+ HugoOperations hugoOps(*ctx->getTab());
+ Ndb* pNdb = GETNDB(step);
+
+ int i = 0;
+ while(i<loops && result != NDBT_FAILED && !ctx->isTestStopped()){
+ g_info << i << ": ";
+
+ if(hugoOps.startTransaction(pNdb) != 0)
+ return NDBT_FAILED;
+
+ if(hugoOps.pkUpdateRecord(pNdb, 1) != 0)
+ return NDBT_FAILED;
+
+ if(hugoOps.execute_NoCommit(pNdb) != 0)
+ return NDBT_FAILED;
+
+ Uint32 transNode= hugoOps.getTransaction()->getConnectedNodeId();
+ int id = i % restarter.getNumDbNodes();
+ int nodeId;
+ while((nodeId = restarter.getDbNodeId(id)) == transNode)
+ id = (id + 1) % restarter.getNumDbNodes();
+
+ ndbout << "Restart node " << nodeId << endl;
+
+ restarter.restartOneDbNode(nodeId,
+ /** initial */ false,
+ /** nostart */ true,
+ /** abort */ true);
+
+ restarter.waitNodesNoStart(&nodeId, 1);
+
+ int res;
+ if(i & 1)
+ res= hugoOps.execute_Commit(pNdb);
+ else
+ res= hugoOps.execute_Rollback(pNdb);
+
+ ndbout_c("res= %d", res);
+
+ hugoOps.closeTransaction(pNdb);
+
+ restarter.startNodes(&nodeId, 1);
+ restarter.waitNodesStarted(&nodeId, 1);
+
+ if(i & 1)
+ {
+ if(res != 286)
+ return NDBT_FAILED;
+ }
+ else
+ {
+ if(res != 0)
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+
+ return NDBT_OK;
+}
+
NDBT_TESTSUITE(testNodeRestart);
TESTCASE("NoLoad",
"Test that one node at a time can be stopped and then restarted "\
@@ -600,6 +665,12 @@ TESTCASE("CommittedRead",
STEP(runDirtyRead);
FINALIZER(runClearTable);
}
+TESTCASE("LateCommit",
+ "Test commit after node failure"){
+ INITIALIZER(runLoadTable);
+ STEP(runLateCommit);
+ FINALIZER(runClearTable);
+}
NDBT_TESTSUITE_END(testNodeRestart);
int main(int argc, const char** argv){
diff --git a/ndb/test/run-test/daily-devel-tests.txt b/ndb/test/run-test/daily-devel-tests.txt
index 2cdd39ffa4c..9812ec2ceaa 100644
--- a/ndb/test/run-test/daily-devel-tests.txt
+++ b/ndb/test/run-test/daily-devel-tests.txt
@@ -71,6 +71,10 @@ args: -n CommittedRead T1
max-time: 2500
cmd: testNodeRestart
+args: -n LateCommit T1
+
+max-time: 2500
+cmd: testNodeRestart
args: -n Terror T6 T13
max-time: 2500
diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh
index 2cfe91da115..632174dc41a 100644
--- a/scripts/mysqlhotcopy.sh
+++ b/scripts/mysqlhotcopy.sh
@@ -272,10 +272,7 @@ foreach my $rdb ( @db_desc ) {
my $negated;
if ($rdb->{t_regex}) {
$t_regex = $rdb->{t_regex}; ## assign temporary regex
- $negated = $t_regex =~ tr/~//d; ## remove and count
- ## negation operator: we
- ## don't allow ~ in table
- ## names
+ $negated = $t_regex =~ s/^~//; ## note and remove negation operator
$t_regex = qr/$t_regex/; ## make regex string from
## user regex
@@ -820,6 +817,16 @@ sub get_list_of_tables {
});
my @dbh_tables = eval { $dbh->tables() };
+
+ ## Remove quotes around table names
+ my $quote = $dbh->get_info(29); # SQL_IDENTIFIER_QUOTE_CHAR
+ if ($quote) {
+ foreach (@dbh_tables) {
+ s/^$quote(.*)$quote$/$1/;
+ s/$quote$quote/$quote/g;
+ }
+ }
+
$dbh->disconnect();
return @dbh_tables;
}
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index a7beae664b9..7ddb7ca25ed 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -1334,7 +1334,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
HA_CREATE_INFO *info)
{
int error;
- uint i,j,recpos,minpos,fieldpos,temp_length,length;
+ uint i,j,recpos,minpos,fieldpos,temp_length,length, create_flags= 0;
bool found_real_auto_increment=0;
enum ha_base_keytype type;
char buff[FN_REFLEN];
@@ -1510,17 +1510,21 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
create_info.data_file_name= info->data_file_name;
create_info.index_file_name=info->index_file_name;
+ if (info->options & HA_LEX_CREATE_TMP_TABLE)
+ create_flags|= HA_CREATE_TMP_TABLE;
+ if (options & HA_OPTION_PACK_RECORD)
+ create_flags|= HA_PACK_RECORD;
+ if (options & HA_OPTION_CHECKSUM)
+ create_flags|= HA_CREATE_CHECKSUM;
+ if (options & HA_OPTION_DELAY_KEY_WRITE)
+ create_flags|= HA_CREATE_DELAY_KEY_WRITE;
+
/* TODO: Check that the following fn_format is really needed */
error=mi_create(fn_format(buff,name,"","",2+4),
table_arg->keys,keydef,
(uint) (recinfo_pos-recinfo), recinfo,
0, (MI_UNIQUEDEF*) 0,
- &create_info,
- (((options & HA_OPTION_PACK_RECORD) ? HA_PACK_RECORD : 0) |
- ((options & HA_OPTION_CHECKSUM) ? HA_CREATE_CHECKSUM : 0) |
- ((options & HA_OPTION_DELAY_KEY_WRITE) ?
- HA_CREATE_DELAY_KEY_WRITE : 0)));
-
+ &create_info, create_flags);
my_free((gptr) recinfo,MYF(0));
DBUG_RETURN(error);
diff --git a/sql/item.cc b/sql/item.cc
index 76cbaa99029..1293d2c94fe 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -384,7 +384,6 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
*/
bool DTCollation::aggregate(DTCollation &dt, uint flags)
{
- nagg++;
if (!my_charset_same(collation, dt.collation))
{
/*
@@ -400,7 +399,6 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags)
else
{
set(dt);
- strong= nagg;
}
}
else if (dt.collation == &my_charset_bin)
@@ -408,7 +406,6 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags)
if (dt.derivation <= derivation)
{
set(dt);
- strong= nagg;
}
else
; // Do nothing
@@ -424,20 +421,18 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags)
dt.collation->state & MY_CS_UNICODE)
{
set(dt);
- strong= nagg;
}
else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) &&
derivation < dt.derivation &&
- dt.derivation >= DERIVATION_COERCIBLE)
+ dt.derivation >= DERIVATION_SYSCONST)
{
// Do nothing;
}
else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) &&
dt.derivation < derivation &&
- derivation >= DERIVATION_COERCIBLE)
+ derivation >= DERIVATION_SYSCONST)
{
set(dt);
- strong= nagg;
}
else
{
@@ -453,7 +448,6 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags)
else if (dt.derivation < derivation)
{
set(dt);
- strong= nagg;
}
else
{
diff --git a/sql/item.h b/sql/item.h
index 97e2b0c0945..adc780677e1 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -31,8 +31,9 @@ void item_init(void); /* Init item functions */
enum Derivation
{
- DERIVATION_IGNORABLE= 4,
- DERIVATION_COERCIBLE= 3,
+ DERIVATION_IGNORABLE= 5,
+ DERIVATION_COERCIBLE= 4,
+ DERIVATION_SYSCONST= 3,
DERIVATION_IMPLICIT= 2,
DERIVATION_NONE= 1,
DERIVATION_EXPLICIT= 0
@@ -61,22 +62,16 @@ class DTCollation {
public:
CHARSET_INFO *collation;
enum Derivation derivation;
- uint nagg; // Total number of aggregated collations.
- uint strong; // Number of the strongest collation.
DTCollation()
{
collation= &my_charset_bin;
derivation= DERIVATION_NONE;
- nagg= 0;
- strong= 0;
}
DTCollation(CHARSET_INFO *collation_arg, Derivation derivation_arg)
{
collation= collation_arg;
derivation= derivation_arg;
- nagg= 0;
- strong= 0;
}
void set(DTCollation &dt)
{
@@ -102,6 +97,7 @@ public:
case DERIVATION_IGNORABLE: return "IGNORABLE";
case DERIVATION_COERCIBLE: return "COERCIBLE";
case DERIVATION_IMPLICIT: return "IMPLICIT";
+ case DERIVATION_SYSCONST: return "SYSCONST";
case DERIVATION_EXPLICIT: return "EXPLICIT";
case DERIVATION_NONE: return "NONE";
default: return "UNKNOWN";
@@ -997,6 +993,8 @@ public:
The following class is used to optimize comparing of date and bigint columns
We need to save the original item, to be able to set the field to the
original value in 'opt_range'.
+ An instance of Item_int_with_ref may refer to a signed or an unsigned
+ integer.
*/
class Item_int_with_ref :public Item_int
@@ -1011,6 +1009,11 @@ public:
{
return ref->save_in_field(field, no_conversions);
}
+ Item *new_item()
+ {
+ return (ref->unsigned_flag)? new Item_uint(ref->name, ref->max_length) :
+ new Item_int(ref->name, ref->max_length);
+ }
};
diff --git a/sql/item_create.cc b/sql/item_create.cc
index d959a6f393a..c0361c928be 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -441,7 +441,7 @@ Item *create_func_version(void)
{
return new Item_string(NullS,server_version,
(uint) strlen(server_version),
- system_charset_info, DERIVATION_IMPLICIT);
+ system_charset_info, DERIVATION_SYSCONST);
}
Item *create_func_weekday(Item* a)
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 895740d2e5e..96250522c4a 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -79,8 +79,6 @@ bool Item_func::agg_arg_collations(DTCollation &c, Item **av, uint count,
uint flags)
{
uint i;
- c.nagg= 0;
- c.strong= 0;
c.set(av[0]->collation);
for (i= 1; i < count; i++)
{
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 0023d7b1f20..2f8d6dd822d 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1509,6 +1509,23 @@ String *Item_func_decode::val_str(String *str)
}
+Item *Item_func_sysconst::safe_charset_converter(CHARSET_INFO *tocs)
+{
+ Item_string *conv;
+ uint conv_errors;
+ String tmp, cstr, *ostr= val_str(&tmp);
+ cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors);
+ if (conv_errors || !(conv= new Item_string(cstr.ptr(), cstr.length(),
+ cstr.charset(),
+ collation.derivation)))
+ {
+ return NULL;
+ }
+ conv->str_value.copy();
+ return conv;
+}
+
+
String *Item_func_database::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index c1c0969672c..0c3ed32fb68 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -337,10 +337,18 @@ public:
};
-class Item_func_database :public Item_str_func
+class Item_func_sysconst :public Item_str_func
{
public:
- Item_func_database() { collation.set(system_charset_info,DERIVATION_IMPLICIT); }
+ Item_func_sysconst()
+ { collation.set(system_charset_info,DERIVATION_SYSCONST); }
+ Item *safe_charset_converter(CHARSET_INFO *tocs);
+};
+
+class Item_func_database :public Item_func_sysconst
+{
+public:
+ Item_func_database() :Item_func_sysconst() {}
String *val_str(String *);
void fix_length_and_dec()
{
@@ -350,10 +358,10 @@ public:
const char *func_name() const { return "database"; }
};
-class Item_func_user :public Item_str_func
+class Item_func_user :public Item_func_sysconst
{
public:
- Item_func_user() { collation.set(system_charset_info, DERIVATION_IMPLICIT); }
+ Item_func_user() :Item_func_sysconst() {}
String *val_str(String *);
void fix_length_and_dec()
{
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 6c77a8934dd..1859daa6fc3 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -890,7 +890,7 @@ extern ulong ha_read_first_count, ha_read_last_count;
extern ulong ha_read_rnd_count, ha_read_rnd_next_count, ha_discover_count;
extern ulong ha_commit_count, ha_rollback_count,table_cache_size;
extern ulong max_connections,max_connect_errors, connect_timeout;
-extern ulong slave_net_timeout;
+extern ulong slave_net_timeout, slave_trans_retries;
extern ulong max_user_connections;
extern ulong long_query_count, what_to_log,flush_time;
extern ulong query_buff_size, thread_stack,thread_stack_min;
@@ -915,7 +915,7 @@ extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types;
extern my_bool opt_safe_show_db, opt_local_infile;
extern my_bool opt_slave_compressed_protocol, use_temp_pool;
extern my_bool opt_readonly, lower_case_file_system;
-extern my_bool opt_enable_named_pipe, opt_sync_frm;
+extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
extern my_bool opt_secure_auth;
extern uint opt_crash_binlog_innodb;
extern char *shared_memory_base_name, *mysqld_unix_port;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index b5674d17901..fb9a1d70512 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -290,7 +290,7 @@ const char *opt_ndbcluster_connectstring= 0;
my_bool opt_ndb_shm, opt_ndb_optimized_node_selection;
#endif
my_bool opt_readonly, use_temp_pool, relay_log_purge;
-my_bool opt_sync_bdb_logs, opt_sync_frm;
+my_bool opt_sync_bdb_logs, opt_sync_frm, opt_allow_suspicious_udfs;
my_bool opt_secure_auth= 0;
my_bool opt_short_log_format= 0;
my_bool opt_log_queries_not_using_indexes= 0;
@@ -311,7 +311,7 @@ ulong server_id, thd_startup_options;
ulong table_cache_size, thread_stack, thread_stack_min, what_to_log;
ulong query_buff_size, slow_launch_time, slave_open_temp_tables;
ulong open_files_limit, max_binlog_size, max_relay_log_size;
-ulong slave_net_timeout;
+ulong slave_net_timeout, slave_trans_retries;
ulong thread_cache_size=0, binlog_cache_size=0, max_binlog_cache_size=0;
ulong query_cache_size=0;
ulong com_stat[(uint) SQLCOM_END], com_other;
@@ -4108,7 +4108,7 @@ enum options_mysqld
OPT_QUERY_CACHE_TYPE, OPT_QUERY_CACHE_WLOCK_INVALIDATE, OPT_RECORD_BUFFER,
OPT_RECORD_RND_BUFFER, OPT_RELAY_LOG_SPACE_LIMIT, OPT_RELAY_LOG_PURGE,
OPT_SLAVE_NET_TIMEOUT, OPT_SLAVE_COMPRESSED_PROTOCOL, OPT_SLOW_LAUNCH_TIME,
- OPT_READONLY, OPT_DEBUGGING,
+ OPT_SLAVE_TRANS_RETRIES, OPT_READONLY, OPT_DEBUGGING,
OPT_SORT_BUFFER, OPT_TABLE_CACHE,
OPT_THREAD_CONCURRENCY, OPT_THREAD_CACHE_SIZE,
OPT_TMP_TABLE_SIZE, OPT_THREAD_STACK,
@@ -4135,7 +4135,7 @@ enum options_mysqld
OPT_BDB_MAX_LOCK,
OPT_ERROR_LOG_FILE,
OPT_DEFAULT_WEEK_FORMAT,
- OPT_RANGE_ALLOC_BLOCK_SIZE,
+ OPT_RANGE_ALLOC_BLOCK_SIZE, OPT_ALLOW_SUSPICIOUS_UDFS,
OPT_QUERY_ALLOC_BLOCK_SIZE, OPT_QUERY_PREALLOC_SIZE,
OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE,
OPT_SYNC_FRM, OPT_SYNC_BINLOG,
@@ -4175,6 +4175,13 @@ struct my_option my_long_options[] =
#endif /* HAVE_REPLICATION */
{"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax. This mode will also set transaction isolation level 'serializable'.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"allow-suspicious-udfs", OPT_ALLOW_SUSPICIOUS_UDFS,
+ "Allows use of UDFs consisting of only one symbol xxx() "
+ "without corresponding xxx_init() or xxx_deinit(). That also means "
+ "that one can load any function from any library, for example exit() "
+ "from libc.so",
+ (gptr*) &opt_allow_suspicious_udfs, (gptr*) &opt_allow_suspicious_udfs,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"basedir", 'b',
"Path to installation directory. All paths are usually resolved relative to this.",
(gptr*) &mysql_home_ptr, (gptr*) &mysql_home_ptr, 0, GET_STR, REQUIRED_ARG,
@@ -5061,7 +5068,7 @@ The minimum value for this variable is 4096.",
(gptr*) &max_system_variables.max_length_for_sort_data, 0, GET_ULONG,
REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
{"max_relay_log_size", OPT_MAX_RELAY_LOG_SIZE,
- "If non-zero: relay log will be rotated automatically when the size exceeds this value; if zero (the default): when the size exceeds max_binlog_size. 0 expected, the minimum value for this variable is 4096.",
+ "If non-zero: relay log will be rotated automatically when the size exceeds this value; if zero (the default): when the size exceeds max_binlog_size. 0 excepted, the minimum value for this variable is 4096.",
(gptr*) &max_relay_log_size, (gptr*) &max_relay_log_size, 0, GET_ULONG,
REQUIRED_ARG, 0L, 0L, 1024*1024L*1024L, 0, IO_SIZE, 0},
{ "max_seeks_for_key", OPT_MAX_SEEKS_FOR_KEY,
@@ -5232,6 +5239,12 @@ The minimum value for this variable is 4096.",
"Number of seconds to wait for more data from a master/slave connection before aborting the read.",
(gptr*) &slave_net_timeout, (gptr*) &slave_net_timeout, 0,
GET_ULONG, REQUIRED_ARG, SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
+ {"slave_transaction_retries", OPT_SLAVE_TRANS_RETRIES,
+ "Number of times the slave SQL thread will retry a transaction in case "
+ "it failed with a deadlock or elapsed lock wait timeout, "
+ "before giving up and stopping.",
+ (gptr*) &slave_trans_retries, (gptr*) &slave_trans_retries, 0,
+ GET_ULONG, REQUIRED_ARG, 0L, 0L, (longlong) ULONG_MAX, 0, 1, 0},
#endif /* HAVE_REPLICATION */
{"slow_launch_time", OPT_SLOW_LAUNCH_TIME,
"If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented.",
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 29ebb2c8817..02b53f701cc 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -320,6 +320,8 @@ sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol",
#ifdef HAVE_REPLICATION
sys_var_long_ptr sys_slave_net_timeout("slave_net_timeout",
&slave_net_timeout);
+sys_var_long_ptr sys_slave_trans_retries("slave_transaction_retries",
+ &slave_trans_retries);
#endif
sys_var_long_ptr sys_slow_launch_time("slow_launch_time",
&slow_launch_time);
@@ -604,6 +606,7 @@ sys_var *sys_variables[]=
#ifdef HAVE_REPLICATION
&sys_slave_compressed_protocol,
&sys_slave_net_timeout,
+ &sys_slave_trans_retries,
&sys_slave_skip_counter,
#endif
&sys_slow_launch_time,
@@ -855,6 +858,7 @@ struct show_var_st init_vars[]= {
{"skip_show_database", (char*) &opt_skip_show_db, SHOW_BOOL},
#ifdef HAVE_REPLICATION
{sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS},
+ {sys_slave_trans_retries.name,(char*) &sys_slave_trans_retries, SHOW_SYS},
#endif
{sys_slow_launch_time.name, (char*) &sys_slow_launch_time, SHOW_SYS},
#ifdef HAVE_SYS_UN_H
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 8ede3f61a0b..104a055417c 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -143,7 +143,7 @@ character-set=latin1
"No paths allowed for shared library",
"Function '%-.64s' already exists",
"Can't open shared library '%-.64s' (errno: %d %-.64s)",
-"Can't find function '%-.64s' in library'",
+"Can't find function '%-.64s' in library",
"Function '%-.64s' is not defined",
"Host '%-.64s' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'",
"Host '%-.64s' is not allowed to connect to this MySQL server",
diff --git a/sql/slave.cc b/sql/slave.cc
index a39cbdbe14b..145f4295075 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -2959,6 +2959,62 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
exec_res = ev->exec_event(rli);
DBUG_ASSERT(rli->sql_thd==thd);
delete ev;
+ if (slave_trans_retries)
+ {
+ if (exec_res &&
+ (thd->net.last_errno == ER_LOCK_DEADLOCK ||
+ thd->net.last_errno == ER_LOCK_WAIT_TIMEOUT) &&
+ !thd->is_fatal_error)
+ {
+ const char *errmsg;
+ /*
+ We were in a transaction which has been rolled back because of a
+ deadlock (currently, InnoDB deadlock detected by InnoDB) or lock
+ wait timeout (innodb_lock_wait_timeout exceeded); let's seek back to
+ BEGIN log event and retry it all again.
+ We have to not only seek but also
+ a) init_master_info(), to seek back to hot relay log's start for later
+ (for when we will come back to this hot log after re-processing the
+ possibly existing old logs where BEGIN is: check_binlog_magic() will
+ then need the cache to be at position 0 (see comments at beginning of
+ init_master_info()).
+ b) init_relay_log_pos(), because the BEGIN may be an older relay log.
+ */
+ if (rli->trans_retries--)
+ {
+ sql_print_information("Slave SQL thread retries transaction");
+ if (init_master_info(rli->mi, 0, 0, 0, SLAVE_SQL))
+ sql_print_error("Failed to initialize the master info structure");
+ else if (init_relay_log_pos(rli,
+ rli->group_relay_log_name,
+ rli->group_relay_log_pos,
+ 1, &errmsg))
+ sql_print_error("Error initializing relay log position: %s",
+ errmsg);
+ else
+ {
+ exec_res= 0;
+ sleep(2); // chance for concurrent connection to get more locks
+ }
+ }
+ else
+ sql_print_error("Slave SQL thread retried transaction %lu time(s) "
+ "in vain, giving up. Consider raising the value of "
+ "the slave_transaction_retries variable.",
+ slave_trans_retries);
+ }
+ if (!((thd->options & OPTION_BEGIN) && opt_using_transactions))
+ {
+ rli->trans_retries= slave_trans_retries; // restart from fresh
+ /*
+ TODO: when merged into 5.0, when slave does auto-rollback if
+ corrupted binlog, this should reset the retry counter too
+ (any rollback should). In fact it will work, as here we are just out
+ of a Format_description_log_event::exec_event() which rolled back.
+ But check repl code in 5.0 for new ha_rollback calls, just in case.
+ */
+ }
+ }
return exec_res;
}
else
@@ -3370,6 +3426,7 @@ slave_begin:
pthread_mutex_lock(&rli->log_space_lock);
rli->ignore_log_space_limit= 0;
pthread_mutex_unlock(&rli->log_space_lock);
+ rli->trans_retries= slave_trans_retries; // start from "no error"
if (init_relay_log_pos(rli,
rli->group_relay_log_name,
diff --git a/sql/slave.h b/sql/slave.h
index bcd79dd4a39..fb7560ec738 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -294,7 +294,9 @@ typedef struct st_relay_log_info
UNTIL_LOG_NAMES_CMP_UNKNOWN= -2, UNTIL_LOG_NAMES_CMP_LESS= -1,
UNTIL_LOG_NAMES_CMP_EQUAL= 0, UNTIL_LOG_NAMES_CMP_GREATER= 1
} until_log_names_cmp_result;
-
+
+ ulong trans_retries;
+
st_relay_log_info();
~st_relay_log_info();
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 46114e2748b..0c3f2a52fd2 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1788,7 +1788,8 @@ static byte* get_key_column(GRANT_COLUMN *buff,uint *length,
class GRANT_TABLE :public Sql_alloc
{
public:
- char *host,*db, *user, *tname, *hash_key, *orig_host;
+ acl_host_and_ip host;
+ char *db, *user, *tname, *hash_key;
ulong privs, cols;
ulong sort;
uint key_length;
@@ -1807,12 +1808,10 @@ GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u,
:privs(p), cols(c)
{
/* Host given by user */
- orig_host= strdup_root(&memex,h);
- /* Convert empty hostname to '%' for easy comparision */
- host= orig_host[0] ? orig_host : (char*) "%";
+ update_hostname(&host, strdup_root(&memex, h));
db = strdup_root(&memex,d);
user = strdup_root(&memex,u);
- sort= get_sort(3,host,db,user);
+ sort= get_sort(3,host.hostname,db,user);
tname= strdup_root(&memex,t);
if (lower_case_table_names)
{
@@ -1831,17 +1830,12 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
{
byte key[MAX_KEY_LENGTH];
- orig_host= host= get_field(&memex, form->field[0]);
+ update_hostname(&host, get_field(&memex, form->field[0]));
db= get_field(&memex,form->field[1]);
user= get_field(&memex,form->field[2]);
if (!user)
user= (char*) "";
- if (!orig_host)
- {
- orig_host= (char*) "";
- host= (char*) "%";
- }
- sort= get_sort(3, orig_host, db, user);
+ sort= get_sort(3, host.hostname, db, user);
tname= get_field(&memex,form->field[3]);
if (!db || !tname)
{
@@ -1868,7 +1862,7 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
if (cols)
{
int key_len;
- col_privs->field[0]->store(orig_host,(uint) strlen(orig_host),
+ col_privs->field[0]->store(host.hostname,(uint) strlen(host.hostname),
&my_charset_latin1);
col_privs->field[1]->store(db,(uint) strlen(db), &my_charset_latin1);
col_privs->field[2]->store(user,(uint) strlen(user), &my_charset_latin1);
@@ -1945,17 +1939,12 @@ static GRANT_TABLE *table_hash_search(const char *host,const char* ip,
{
if (exact)
{
- if ((host &&
- !my_strcasecmp(&my_charset_latin1, host, grant_table->host)) ||
- (ip && !strcmp(ip,grant_table->host)))
+ if (compare_hostname(&grant_table->host, host, ip))
return grant_table;
}
else
{
- if (((host && !wild_case_compare(&my_charset_latin1,
- host,grant_table->host)) ||
- (ip && !wild_case_compare(&my_charset_latin1,
- ip,grant_table->host))) &&
+ if (compare_hostname(&grant_table->host, host, ip) &&
(!found || found->sort < grant_table->sort))
found=grant_table; // Host ok
}
@@ -2692,7 +2681,7 @@ my_bool grant_init(THD *org_thd)
if (check_no_resolve)
{
- if (hostname_requires_resolving(mem_check->host))
+ if (hostname_requires_resolving(mem_check->host.hostname))
{
sql_print_warning("'tables_priv' entry '%s %s@%s' "
"ignored in --skip-name-resolve mode.",
@@ -2981,10 +2970,7 @@ bool check_grant_db(THD *thd,const char *db)
idx);
if (len < grant_table->key_length &&
!memcmp(grant_table->hash_key,helping,len) &&
- (thd->host && !wild_case_compare(&my_charset_latin1,
- thd->host,grant_table->host) ||
- (thd->ip && !wild_case_compare(&my_charset_latin1,
- thd->ip,grant_table->host))))
+ compare_hostname(&grant_table->host, thd->host, thd->ip))
{
error=0; // Found match
break;
@@ -3324,7 +3310,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (!strcmp(lex_user->user.str,user) &&
!my_strcasecmp(&my_charset_latin1, lex_user->host.str,
- grant_table->orig_host))
+ grant_table->host.hostname))
{
ulong table_access= grant_table->privs;
if ((table_access | grant_table->cols) != 0)
@@ -3606,7 +3592,7 @@ int mysql_drop_user(THD *thd, List <LEX_USER> &list)
counter);
if (!(user=grant_table->user))
user= "";
- if (!(host=grant_table->host))
+ if (!(host=grant_table->host.hostname))
host= "";
if (!strcmp(user_name->user.str,user) &&
@@ -3735,7 +3721,7 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list)
counter);
if (!(user=grant_table->user))
user= "";
- if (!(host=grant_table->host))
+ if (!(host=grant_table->host.hostname))
host= "";
if (!strcmp(lex_user->user.str,user) &&
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index 0bb8ac8a28b..05df069d69a 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -74,32 +74,49 @@ static HASH udf_hash;
static rw_lock_t THR_LOCK_udf;
-static udf_func *add_udf(LEX_STRING *name, Item_result ret, char *dl,
- Item_udftype typ);
+static udf_func *add_udf(LEX_STRING *name, Item_result ret,
+ char *dl, Item_udftype typ);
static void del_udf(udf_func *udf);
static void *find_udf_dl(const char *dl);
-
-static void init_syms(udf_func *tmp)
+static char *init_syms(udf_func *tmp, char *nm)
{
- char nm[MAX_FIELD_NAME+16],*end;
+ char *end;
+
+ if (!((tmp->func= dlsym(tmp->dlhandle, tmp->name.str))))
+ return tmp->name.str;
- tmp->func = dlsym(tmp->dlhandle, tmp->name.str);
end=strmov(nm,tmp->name.str);
- (void) strmov(end,"_init");
- tmp->func_init = dlsym(tmp->dlhandle, nm);
- (void) strmov(end,"_deinit");
- tmp->func_deinit = dlsym(tmp->dlhandle, nm);
+
if (tmp->type == UDFTYPE_AGGREGATE)
{
- (void)strmov( end, "_clear" );
- tmp->func_clear = dlsym( tmp->dlhandle, nm );
- (void)strmov( end, "_add" );
- tmp->func_add = dlsym( tmp->dlhandle, nm );
- /* Give error if _clear and _add doesn't exists */
- if (!tmp->func_clear || ! tmp->func_add)
- tmp->func= 0;
+ (void)strmov(end, "_clear");
+ if (!((tmp->func_clear= dlsym(tmp->dlhandle, nm))))
+ return nm;
+ (void)strmov(end, "_add");
+ if (!((tmp->func_add= dlsym(tmp->dlhandle, nm))))
+ return nm;
+ }
+
+ (void) strmov(end,"_deinit");
+ tmp->func_deinit= dlsym(tmp->dlhandle, nm);
+
+ (void) strmov(end,"_init");
+ tmp->func_init= dlsym(tmp->dlhandle, nm);
+
+ /*
+ to prefent loading "udf" from, e.g. libc.so
+ let's ensure that at least one auxiliary symbol is defined
+ */
+ if (!tmp->func_init && !tmp->func_deinit && tmp->type != UDFTYPE_AGGREGATE)
+ {
+ if (opt_allow_suspicious_udfs)
+ sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), nm);
+ else
+ return nm;
}
+
+ return 0;
}
extern "C" byte* get_hash_key(const byte *buff,uint *length,
@@ -111,7 +128,7 @@ extern "C" byte* get_hash_key(const byte *buff,uint *length,
}
/*
-** Read all predeclared functions from func@mysql and accept all that
+** Read all predeclared functions from mysql.func and accept all that
** can be used.
*/
@@ -153,7 +170,7 @@ void udf_init()
if (simple_open_n_lock_tables(new_thd, &tables))
{
DBUG_PRINT("error",("Can't open udf table"));
- sql_print_error("Can't open the mysql/func table. Please run the mysql_install_db script to create it.");
+ sql_print_error("Can't open the mysql.func table. Please run the mysql_install_db script to create it.");
goto end;
}
@@ -171,10 +188,23 @@ void udf_init()
if (table->fields >= 4) // New func table
udftype=(Item_udftype) table->field[3]->val_int();
- if (!(tmp = add_udf(&name,(Item_result) table->field[1]->val_int(),
- dl_name, udftype)))
+ /*
+ Ensure that the .dll doesn't have a path
+ This is done to ensure that only approved dll from the system
+ directories are used (to make this even remotely secure).
+ */
+ if (strchr(dl_name, '/') || name.length > NAME_LEN)
+ {
+ sql_print_error("Invalid row in mysql.func table for function '%.64s'",
+ name.str);
+ continue;
+ }
+
+
+ if (!(tmp= add_udf(&name,(Item_result) table->field[1]->val_int(),
+ dl_name, udftype)))
{
- sql_print_error("Can't alloc memory for udf function: name");
+ sql_print_error("Can't alloc memory for udf function: '%.64s'", name.str);
continue;
}
@@ -191,13 +221,15 @@ void udf_init()
new_dl=1;
}
tmp->dlhandle = dl;
- init_syms(tmp);
- if (!tmp->func)
{
- sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), name);
- del_udf(tmp);
- if (new_dl)
- dlclose(dl);
+ char buf[MAX_FIELD_NAME+16], *missing;
+ if ((missing= init_syms(tmp, buf)))
+ {
+ sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), missing);
+ del_udf(tmp);
+ if (new_dl)
+ dlclose(dl);
+ }
}
}
if (error > 0)
@@ -239,7 +271,7 @@ void udf_free()
{
initialized= 0;
rwlock_destroy(&THR_LOCK_udf);
- }
+ }
DBUG_VOID_RETURN;
}
@@ -406,12 +438,13 @@ int mysql_create_function(THD *thd,udf_func *udf)
new_dl=1;
}
udf->dlhandle=dl;
- init_syms(udf);
-
- if (udf->func == NULL)
{
- net_printf(thd, ER_CANT_FIND_DL_ENTRY, udf->name);
- goto err;
+ char buf[MAX_FIELD_NAME+16], *missing;
+ if ((missing= init_syms(udf, buf)))
+ {
+ net_printf(thd, ER_CANT_FIND_DL_ENTRY, missing);
+ goto err;
+ }
}
udf->name.str=strdup_root(&mem,udf->name.str);
udf->dl=strdup_root(&mem,udf->dl);
@@ -427,7 +460,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
u_d->func_clear=udf->func_clear;
u_d->func_add=udf->func_add;
- /* create entry in mysql/func table */
+ /* create entry in mysql.func table */
bzero((char*) &tables,sizeof(tables));
tables.db= (char*) "mysql";
@@ -447,7 +480,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
close_thread_tables(thd);
if (error)
{
- net_printf(thd, ER_ERROR_ON_WRITE, "func@mysql",error);
+ net_printf(thd, ER_ERROR_ON_WRITE, "mysql.func",error);
del_udf(u_d);
goto err;
}
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 882316d57d7..5fd59500ace 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -215,8 +215,6 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
select_limit_cnt= sl->select_limit+sl->offset_limit;
if (select_limit_cnt < sl->select_limit)
select_limit_cnt= HA_POS_ERROR; // no limit
- if (select_limit_cnt == HA_POS_ERROR || sl->braces)
- sl->options&= ~OPTION_FOUND_ROWS;
can_skip_order_by= is_union &&
(!sl->braces || select_limit_cnt == HA_POS_ERROR);
@@ -342,7 +340,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
if (arena->is_stmt_prepare())
{
/* prepare fake select to initialize it correctly */
- ulong options_tmp= init_prepare_fake_select_lex(thd);
+ (void) init_prepare_fake_select_lex(thd);
if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->options,
result)))
{
@@ -447,21 +445,14 @@ int st_select_lex_unit::exec()
if (select_limit_cnt < sl->select_limit)
select_limit_cnt= HA_POS_ERROR; // no limit
- /*
- When using braces, SQL_CALC_FOUND_ROWS affects the whole query.
- We don't calculate found_rows() per union part
- */
- if (select_limit_cnt == HA_POS_ERROR || sl->braces)
- sl->options&= ~OPTION_FOUND_ROWS;
- else
- {
- /*
- We are doing an union without braces. In this case
- SQL_CALC_FOUND_ROWS should be done on all sub parts
- */
- sl->options|= found_rows_for_union;
- }
- sl->join->select_options=sl->options;
+ /*
+ When using braces, SQL_CALC_FOUND_ROWS affects the whole query:
+ we don't calculate found_rows() per union part.
+ Otherwise, SQL_CALC_FOUND_ROWS should be done on all sub parts.
+ */
+ sl->join->select_options=
+ (select_limit_cnt == HA_POS_ERROR || sl->braces) ?
+ sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
res= sl->join->optimize();
}
if (!res)
@@ -493,7 +484,8 @@ int st_select_lex_unit::exec()
}
/* Needed for the following test and for records_at_start in next loop */
table->file->info(HA_STATUS_VARIABLE);
- if (found_rows_for_union & sl->options)
+ if (found_rows_for_union && !sl->braces &&
+ select_limit_cnt != HA_POS_ERROR)
{
/*
This is a union without braces. Remember the number of rows that
diff --git a/sql/table.cc b/sql/table.cc
index 064d7f1afc1..cdcd5148787 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1229,6 +1229,10 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo,
uint key_length;
ulong length;
char fill[IO_SIZE];
+ int create_flags= O_RDWR | O_TRUNC;
+
+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
+ create_flags|= O_EXCL | O_NOFOLLOW;
#if SIZEOF_OFF_T > 4
/* Fix this when we have new .frm files; Current limit is 4G rows (QQ) */
@@ -1243,7 +1247,7 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo,
*/
set_if_smaller(create_info->raid_chunks, 255);
- if ((file=my_create(name,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0)
+ if ((file= my_create(name, CREATE_MODE, create_flags, MYF(MY_WME))) >= 0)
{
bzero((char*) fileinfo,64);
fileinfo[0]=(uchar) 254; fileinfo[1]= 1; fileinfo[2]= FRM_VER+3; // Header
diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c
index 98389a9a5a4..d843971b93f 100644
--- a/strings/ctype-win1250ch.c
+++ b/strings/ctype-win1250ch.c
@@ -416,7 +416,7 @@ static struct wordvalue doubles[] = {
#define NEXT_CMP_VALUE(src, p, pass, value, len) \
while (1) { \
if (IS_END(p, src, len)) { \
- if (pass == 0) { p = src; pass++; } \
+ if (pass == 0 && len > 0) { p= src; pass++; } \
else { value = 0; break; } \
} \
value = ((pass == 0) ? _sort_order_win1250ch1[*p] \