diff options
33 files changed, 778 insertions, 247 deletions
diff --git a/client/mysql.cc b/client/mysql.cc index 0a0fca286e1..28d781aff8b 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -4798,10 +4798,11 @@ com_status(String *buffer __attribute__((unused)), tee_fprintf(stdout, "Protocol:\t\tCompressed\n"); #endif - if ((status_str= mysql_stat(&mysql)) && !mysql_error(&mysql)[0]) + const char *pos; + if ((status_str= mysql_stat(&mysql)) && !mysql_error(&mysql)[0] && + (pos= strchr(status_str,' '))) { ulong sec; - const char *pos= strchr(status_str,' '); /* print label */ tee_fprintf(stdout, "%.*s\t\t\t", (int) (pos-status_str), status_str); if ((status_str= str2int(pos,10,0,LONG_MAX,(long*) &sec))) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 4e4970bacab..c10dc20e7d7 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -1171,6 +1171,8 @@ int main(int argc, char **argv) { int fd= create_temp_file(cnf_file_path, opt_tmpdir[0] ? opt_tmpdir : NULL, "mysql_upgrade-", O_CREAT | O_WRONLY, MYF(MY_FAE)); + if (fd < 0) + die(NULL); my_write(fd, USTRING_WITH_LEN( "[client]\n"), MYF(MY_FAE)); my_write(fd, (uchar*)ds_args.str, ds_args.length, MYF(MY_FAE)); my_close(fd, MYF(0)); diff --git a/client/mysqldump.c b/client/mysqldump.c index ca47f89268e..aead4caf506 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -92,8 +92,7 @@ static void add_load_option(DYNAMIC_STRING *str, const char *option, const char *option_value); -static ulong find_set(TYPELIB *lib, const char *x, size_t length, - char **err_pos, uint *err_len); +static ulong find_set(TYPELIB *, const char *, size_t, char **, uint *); static char *alloc_query_str(ulong size); static void field_escape(DYNAMIC_STRING* in, const char *from); @@ -5471,7 +5470,7 @@ static ulong find_set(TYPELIB *lib, const char *x, size_t length, var_len= (uint) (pos - start); strmake(buff, start, MY_MIN(sizeof(buff) - 1, var_len)); find= find_type(buff, lib, FIND_TYPE_BASIC); - if (!find) + if (find <= 0) { *err_pos= (char*) start; *err_len= var_len; diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 216359c82ec..7f03cb355f8 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -675,7 +675,7 @@ int main(int argc, char **argv) MYF(0)))) return -2; - for (counter= 0; *argv != NULL; argv++) /* Loop through tables */ + for (; *argv != NULL; argv++) /* Loop through tables */ { pthread_mutex_lock(&counter_mutex); while (counter == opt_use_threads) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 504eadcf2a8..99e4e4dfc66 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -600,7 +600,7 @@ void do_eval(DYNAMIC_STRING *query_eval, const char *query, void str_to_file(const char *fname, char *str, int size); void str_to_file2(const char *fname, char *str, int size, my_bool append); -void fix_win_paths(const char *val, int len); +void fix_win_paths(const char *val, size_t len); const char *get_errname_from_code (uint error_code); int multi_reg_replace(struct st_replace_regex* r,char* val); @@ -814,8 +814,7 @@ public: LogFile log_file; LogFile progress_file; -void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val, - int len); +void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val, size_t len); void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val); void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val); void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING* ds_input, @@ -2653,6 +2652,7 @@ void var_query_set(VAR *var, const char *query, const char** query_end) if (!mysql) { struct st_command command; + DBUG_ASSERT(query_end); memset(&command, 0, sizeof(command)); command.query= (char*)query; command.first_word_len= (*query_end - query); @@ -7488,7 +7488,7 @@ void free_win_path_patterns() => all \ from c:\mysql\m... until next space is converted into / */ -void fix_win_paths(const char *val, int len) +void fix_win_paths(const char *val, size_t len) { uint i; char *p; @@ -11013,7 +11013,7 @@ void free_pointer_array(POINTER_ARRAY *pa) /* Append the string to ds, with optional replace */ void replace_dynstr_append_mem(DYNAMIC_STRING *ds, - const char *val, int len) + const char *val, size_t len) { char lower[512]; #ifdef __WIN__ diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 49a033626ee..da418accd6c 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4701,7 +4701,7 @@ pk SET SESSION sql_mode=@old_sql_mode; drop table t2, t1; drop view v1; -End of 5.0 tests. +# End of 5.0 tests. create table t_out (subcase char(3), a1 char(2), b1 char(2), c1 char(2)); create table t_in (a2 char(2), b2 char(2), c2 char(2)); @@ -5576,7 +5576,7 @@ insert into t2 values ('x'), ('y'); select * from t2 where a=(select a from t1) and a='x'; ERROR 21000: Subquery returns more than 1 row drop table t1,t2; -End of 5.1 tests +# End of 5.1 tests # # Bug #11765713 58705: # OPTIMIZER LET ENGINE DEPEND ON UNINITIALIZED VALUES @@ -6188,7 +6188,7 @@ WHERE (c_sq1_alias1.col_int_nokey != @var2 OR c_sq1_alias1.pk != @var3)) ) AS alias3; pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey DROP TABLE t1,t2; -End of 5.2 tests +# End of 5.2 tests # # BUG#779885: Crash in eliminate_item_equal with materialization=on in # @@ -7145,9 +7145,10 @@ INSERT INTO t1 VALUES (1),(2); CREATE TABLE t2 (f2 INT, KEY(f2)); INSERT INTO t2 VALUES (3); CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t2; +SELECT ( SELECT MIN(t2.f2) FROM t1 ) AS sq FROM t2 GROUP BY sq; +ERROR 42000: Can't group on 'sq' SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; -sq -3 +ERROR 42000: Can't group on 'sq' SELECT * FROM v2 where ( SELECT MIN(v2.f2) FROM t1 ) > 0; f2 3 @@ -7155,9 +7156,10 @@ SELECT count(*) FROM v2 group by ( SELECT MIN(v2.f2) FROM t1 ); count(*) 1 delete from t1; +SELECT ( SELECT MIN(t2.f2) FROM t1 ) AS sq FROM t2 GROUP BY sq; +ERROR 42000: Can't group on 'sq' SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; -sq -NULL +ERROR 42000: Can't group on 'sq' drop view v2; drop table t1,t2; # @@ -7172,6 +7174,29 @@ f1 f2 foo bar DROP TABLE t1; # +# MDEV-10146: Wrong result (or questionable result and behavior) +# with aggregate function in uncorrelated SELECT subquery +# +CREATE TABLE t1 (f1 INT); +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (f2 int); +INSERT INTO t2 VALUES (3); +SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1; +( SELECT MAX(f1) FROM t2 ) +2 +SELECT ( SELECT MAX(f1) FROM t2 ) FROM v1; +( SELECT MAX(f1) FROM t2 ) +2 +INSERT INTO t2 VALUES (4); +SELECT ( SELECT MAX(f1) FROM t2 ) FROM v1; +ERROR 21000: Subquery returns more than 1 row +SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1; +ERROR 21000: Subquery returns more than 1 row +drop view v1; +drop table t1,t2; +# End of 10.0 tests +# # MDEV-9487: Server crashes in Time_and_counter_tracker::incr_loops # with UNION in ALL subquery # @@ -7198,4 +7223,4 @@ SELECT * FROM t1, t2 WHERE f3 = f2 AND f1 > ANY ( SELECT 'foo'); f1 f2 f3 DROP TABLE t1, t2; SET NAMES default; -End of 10.1 tests +# End of 10.1 tests diff --git a/mysql-test/r/subselect_no_exists_to_in.result b/mysql-test/r/subselect_no_exists_to_in.result index d968a81c638..5382e291dfc 100644 --- a/mysql-test/r/subselect_no_exists_to_in.result +++ b/mysql-test/r/subselect_no_exists_to_in.result @@ -4703,7 +4703,7 @@ pk SET SESSION sql_mode=@old_sql_mode; drop table t2, t1; drop view v1; -End of 5.0 tests. +# End of 5.0 tests. create table t_out (subcase char(3), a1 char(2), b1 char(2), c1 char(2)); create table t_in (a2 char(2), b2 char(2), c2 char(2)); @@ -5578,7 +5578,7 @@ insert into t2 values ('x'), ('y'); select * from t2 where a=(select a from t1) and a='x'; ERROR 21000: Subquery returns more than 1 row drop table t1,t2; -End of 5.1 tests +# End of 5.1 tests # # Bug #11765713 58705: # OPTIMIZER LET ENGINE DEPEND ON UNINITIALIZED VALUES @@ -6188,7 +6188,7 @@ WHERE (c_sq1_alias1.col_int_nokey != @var2 OR c_sq1_alias1.pk != @var3)) ) AS alias3; pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey DROP TABLE t1,t2; -End of 5.2 tests +# End of 5.2 tests # # BUG#779885: Crash in eliminate_item_equal with materialization=on in # @@ -7145,9 +7145,10 @@ INSERT INTO t1 VALUES (1),(2); CREATE TABLE t2 (f2 INT, KEY(f2)); INSERT INTO t2 VALUES (3); CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t2; +SELECT ( SELECT MIN(t2.f2) FROM t1 ) AS sq FROM t2 GROUP BY sq; +ERROR 42000: Can't group on 'sq' SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; -sq -3 +ERROR 42000: Can't group on 'sq' SELECT * FROM v2 where ( SELECT MIN(v2.f2) FROM t1 ) > 0; f2 3 @@ -7155,9 +7156,10 @@ SELECT count(*) FROM v2 group by ( SELECT MIN(v2.f2) FROM t1 ); count(*) 1 delete from t1; +SELECT ( SELECT MIN(t2.f2) FROM t1 ) AS sq FROM t2 GROUP BY sq; +ERROR 42000: Can't group on 'sq' SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; -sq -NULL +ERROR 42000: Can't group on 'sq' drop view v2; drop table t1,t2; # @@ -7172,6 +7174,29 @@ f1 f2 foo bar DROP TABLE t1; # +# MDEV-10146: Wrong result (or questionable result and behavior) +# with aggregate function in uncorrelated SELECT subquery +# +CREATE TABLE t1 (f1 INT); +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (f2 int); +INSERT INTO t2 VALUES (3); +SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1; +( SELECT MAX(f1) FROM t2 ) +2 +SELECT ( SELECT MAX(f1) FROM t2 ) FROM v1; +( SELECT MAX(f1) FROM t2 ) +2 +INSERT INTO t2 VALUES (4); +SELECT ( SELECT MAX(f1) FROM t2 ) FROM v1; +ERROR 21000: Subquery returns more than 1 row +SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1; +ERROR 21000: Subquery returns more than 1 row +drop view v1; +drop table t1,t2; +# End of 10.0 tests +# # MDEV-9487: Server crashes in Time_and_counter_tracker::incr_loops # with UNION in ALL subquery # @@ -7198,7 +7223,7 @@ SELECT * FROM t1, t2 WHERE f3 = f2 AND f1 > ANY ( SELECT 'foo'); f1 f2 f3 DROP TABLE t1, t2; SET NAMES default; -End of 10.1 tests +# End of 10.1 tests set optimizer_switch=default; select @@optimizer_switch like '%exists_to_in=off%'; @@optimizer_switch like '%exists_to_in=off%' diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result index 19a936e86c7..255f8e30ccf 100644 --- a/mysql-test/r/subselect_no_mat.result +++ b/mysql-test/r/subselect_no_mat.result @@ -4701,7 +4701,7 @@ pk SET SESSION sql_mode=@old_sql_mode; drop table t2, t1; drop view v1; -End of 5.0 tests. +# End of 5.0 tests. create table t_out (subcase char(3), a1 char(2), b1 char(2), c1 char(2)); create table t_in (a2 char(2), b2 char(2), c2 char(2)); @@ -5576,7 +5576,7 @@ insert into t2 values ('x'), ('y'); select * from t2 where a=(select a from t1) and a='x'; ERROR 21000: Subquery returns more than 1 row drop table t1,t2; -End of 5.1 tests +# End of 5.1 tests # # Bug #11765713 58705: # OPTIMIZER LET ENGINE DEPEND ON UNINITIALIZED VALUES @@ -6183,7 +6183,7 @@ WHERE (c_sq1_alias1.col_int_nokey != @var2 OR c_sq1_alias1.pk != @var3)) ) AS alias3; pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey DROP TABLE t1,t2; -End of 5.2 tests +# End of 5.2 tests # # BUG#779885: Crash in eliminate_item_equal with materialization=on in # @@ -7138,9 +7138,10 @@ INSERT INTO t1 VALUES (1),(2); CREATE TABLE t2 (f2 INT, KEY(f2)); INSERT INTO t2 VALUES (3); CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t2; +SELECT ( SELECT MIN(t2.f2) FROM t1 ) AS sq FROM t2 GROUP BY sq; +ERROR 42000: Can't group on 'sq' SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; -sq -3 +ERROR 42000: Can't group on 'sq' SELECT * FROM v2 where ( SELECT MIN(v2.f2) FROM t1 ) > 0; f2 3 @@ -7148,9 +7149,10 @@ SELECT count(*) FROM v2 group by ( SELECT MIN(v2.f2) FROM t1 ); count(*) 1 delete from t1; +SELECT ( SELECT MIN(t2.f2) FROM t1 ) AS sq FROM t2 GROUP BY sq; +ERROR 42000: Can't group on 'sq' SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; -sq -NULL +ERROR 42000: Can't group on 'sq' drop view v2; drop table t1,t2; # @@ -7165,6 +7167,29 @@ f1 f2 foo bar DROP TABLE t1; # +# MDEV-10146: Wrong result (or questionable result and behavior) +# with aggregate function in uncorrelated SELECT subquery +# +CREATE TABLE t1 (f1 INT); +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (f2 int); +INSERT INTO t2 VALUES (3); +SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1; +( SELECT MAX(f1) FROM t2 ) +2 +SELECT ( SELECT MAX(f1) FROM t2 ) FROM v1; +( SELECT MAX(f1) FROM t2 ) +2 +INSERT INTO t2 VALUES (4); +SELECT ( SELECT MAX(f1) FROM t2 ) FROM v1; +ERROR 21000: Subquery returns more than 1 row +SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1; +ERROR 21000: Subquery returns more than 1 row +drop view v1; +drop table t1,t2; +# End of 10.0 tests +# # MDEV-9487: Server crashes in Time_and_counter_tracker::incr_loops # with UNION in ALL subquery # @@ -7191,7 +7216,7 @@ SELECT * FROM t1, t2 WHERE f3 = f2 AND f1 > ANY ( SELECT 'foo'); f1 f2 f3 DROP TABLE t1, t2; SET NAMES default; -End of 10.1 tests +# End of 10.1 tests set optimizer_switch=default; select @@optimizer_switch like '%materialization=on%'; @@optimizer_switch like '%materialization=on%' diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result index 1293e1de412..938c8edc2e9 100644 --- a/mysql-test/r/subselect_no_opts.result +++ b/mysql-test/r/subselect_no_opts.result @@ -4697,7 +4697,7 @@ pk SET SESSION sql_mode=@old_sql_mode; drop table t2, t1; drop view v1; -End of 5.0 tests. +# End of 5.0 tests. create table t_out (subcase char(3), a1 char(2), b1 char(2), c1 char(2)); create table t_in (a2 char(2), b2 char(2), c2 char(2)); @@ -5572,7 +5572,7 @@ insert into t2 values ('x'), ('y'); select * from t2 where a=(select a from t1) and a='x'; ERROR 21000: Subquery returns more than 1 row drop table t1,t2; -End of 5.1 tests +# End of 5.1 tests # # Bug #11765713 58705: # OPTIMIZER LET ENGINE DEPEND ON UNINITIALIZED VALUES @@ -6179,7 +6179,7 @@ WHERE (c_sq1_alias1.col_int_nokey != @var2 OR c_sq1_alias1.pk != @var3)) ) AS alias3; pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey DROP TABLE t1,t2; -End of 5.2 tests +# End of 5.2 tests # # BUG#779885: Crash in eliminate_item_equal with materialization=on in # @@ -7136,9 +7136,10 @@ INSERT INTO t1 VALUES (1),(2); CREATE TABLE t2 (f2 INT, KEY(f2)); INSERT INTO t2 VALUES (3); CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t2; +SELECT ( SELECT MIN(t2.f2) FROM t1 ) AS sq FROM t2 GROUP BY sq; +ERROR 42000: Can't group on 'sq' SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; -sq -3 +ERROR 42000: Can't group on 'sq' SELECT * FROM v2 where ( SELECT MIN(v2.f2) FROM t1 ) > 0; f2 3 @@ -7146,9 +7147,10 @@ SELECT count(*) FROM v2 group by ( SELECT MIN(v2.f2) FROM t1 ); count(*) 1 delete from t1; +SELECT ( SELECT MIN(t2.f2) FROM t1 ) AS sq FROM t2 GROUP BY sq; +ERROR 42000: Can't group on 'sq' SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; -sq -NULL +ERROR 42000: Can't group on 'sq' drop view v2; drop table t1,t2; # @@ -7163,6 +7165,29 @@ f1 f2 foo bar DROP TABLE t1; # +# MDEV-10146: Wrong result (or questionable result and behavior) +# with aggregate function in uncorrelated SELECT subquery +# +CREATE TABLE t1 (f1 INT); +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (f2 int); +INSERT INTO t2 VALUES (3); +SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1; +( SELECT MAX(f1) FROM t2 ) +2 +SELECT ( SELECT MAX(f1) FROM t2 ) FROM v1; +( SELECT MAX(f1) FROM t2 ) +2 +INSERT INTO t2 VALUES (4); +SELECT ( SELECT MAX(f1) FROM t2 ) FROM v1; +ERROR 21000: Subquery returns more than 1 row +SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1; +ERROR 21000: Subquery returns more than 1 row +drop view v1; +drop table t1,t2; +# End of 10.0 tests +# # MDEV-9487: Server crashes in Time_and_counter_tracker::incr_loops # with UNION in ALL subquery # @@ -7189,5 +7214,5 @@ SELECT * FROM t1, t2 WHERE f3 = f2 AND f1 > ANY ( SELECT 'foo'); f1 f2 f3 DROP TABLE t1, t2; SET NAMES default; -End of 10.1 tests +# End of 10.1 tests set @optimizer_switch_for_subselect_test=null; diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result index cc3d20ef163..9a37719c38a 100644 --- a/mysql-test/r/subselect_no_scache.result +++ b/mysql-test/r/subselect_no_scache.result @@ -4707,7 +4707,7 @@ pk SET SESSION sql_mode=@old_sql_mode; drop table t2, t1; drop view v1; -End of 5.0 tests. +# End of 5.0 tests. create table t_out (subcase char(3), a1 char(2), b1 char(2), c1 char(2)); create table t_in (a2 char(2), b2 char(2), c2 char(2)); @@ -5582,7 +5582,7 @@ insert into t2 values ('x'), ('y'); select * from t2 where a=(select a from t1) and a='x'; ERROR 21000: Subquery returns more than 1 row drop table t1,t2; -End of 5.1 tests +# End of 5.1 tests # # Bug #11765713 58705: # OPTIMIZER LET ENGINE DEPEND ON UNINITIALIZED VALUES @@ -6194,7 +6194,7 @@ WHERE (c_sq1_alias1.col_int_nokey != @var2 OR c_sq1_alias1.pk != @var3)) ) AS alias3; pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey DROP TABLE t1,t2; -End of 5.2 tests +# End of 5.2 tests # # BUG#779885: Crash in eliminate_item_equal with materialization=on in # @@ -7151,9 +7151,10 @@ INSERT INTO t1 VALUES (1),(2); CREATE TABLE t2 (f2 INT, KEY(f2)); INSERT INTO t2 VALUES (3); CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t2; +SELECT ( SELECT MIN(t2.f2) FROM t1 ) AS sq FROM t2 GROUP BY sq; +ERROR 42000: Can't group on 'sq' SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; -sq -3 +ERROR 42000: Can't group on 'sq' SELECT * FROM v2 where ( SELECT MIN(v2.f2) FROM t1 ) > 0; f2 3 @@ -7161,9 +7162,10 @@ SELECT count(*) FROM v2 group by ( SELECT MIN(v2.f2) FROM t1 ); count(*) 1 delete from t1; +SELECT ( SELECT MIN(t2.f2) FROM t1 ) AS sq FROM t2 GROUP BY sq; +ERROR 42000: Can't group on 'sq' SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; -sq -NULL +ERROR 42000: Can't group on 'sq' drop view v2; drop table t1,t2; # @@ -7178,6 +7180,29 @@ f1 f2 foo bar DROP TABLE t1; # +# MDEV-10146: Wrong result (or questionable result and behavior) +# with aggregate function in uncorrelated SELECT subquery +# +CREATE TABLE t1 (f1 INT); +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (f2 int); +INSERT INTO t2 VALUES (3); +SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1; +( SELECT MAX(f1) FROM t2 ) +2 +SELECT ( SELECT MAX(f1) FROM t2 ) FROM v1; +( SELECT MAX(f1) FROM t2 ) +2 +INSERT INTO t2 VALUES (4); +SELECT ( SELECT MAX(f1) FROM t2 ) FROM v1; +ERROR 21000: Subquery returns more than 1 row +SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1; +ERROR 21000: Subquery returns more than 1 row +drop view v1; +drop table t1,t2; +# End of 10.0 tests +# # MDEV-9487: Server crashes in Time_and_counter_tracker::incr_loops # with UNION in ALL subquery # @@ -7204,7 +7229,7 @@ SELECT * FROM t1, t2 WHERE f3 = f2 AND f1 > ANY ( SELECT 'foo'); f1 f2 f3 DROP TABLE t1, t2; SET NAMES default; -End of 10.1 tests +# End of 10.1 tests set optimizer_switch=default; select @@optimizer_switch like '%subquery_cache=on%'; @@optimizer_switch like '%subquery_cache=on%' diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result index 2bbde7b397f..c66fef2eb9b 100644 --- a/mysql-test/r/subselect_no_semijoin.result +++ b/mysql-test/r/subselect_no_semijoin.result @@ -4697,7 +4697,7 @@ pk SET SESSION sql_mode=@old_sql_mode; drop table t2, t1; drop view v1; -End of 5.0 tests. +# End of 5.0 tests. create table t_out (subcase char(3), a1 char(2), b1 char(2), c1 char(2)); create table t_in (a2 char(2), b2 char(2), c2 char(2)); @@ -5572,7 +5572,7 @@ insert into t2 values ('x'), ('y'); select * from t2 where a=(select a from t1) and a='x'; ERROR 21000: Subquery returns more than 1 row drop table t1,t2; -End of 5.1 tests +# End of 5.1 tests # # Bug #11765713 58705: # OPTIMIZER LET ENGINE DEPEND ON UNINITIALIZED VALUES @@ -6179,7 +6179,7 @@ WHERE (c_sq1_alias1.col_int_nokey != @var2 OR c_sq1_alias1.pk != @var3)) ) AS alias3; pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey DROP TABLE t1,t2; -End of 5.2 tests +# End of 5.2 tests # # BUG#779885: Crash in eliminate_item_equal with materialization=on in # @@ -7136,9 +7136,10 @@ INSERT INTO t1 VALUES (1),(2); CREATE TABLE t2 (f2 INT, KEY(f2)); INSERT INTO t2 VALUES (3); CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t2; +SELECT ( SELECT MIN(t2.f2) FROM t1 ) AS sq FROM t2 GROUP BY sq; +ERROR 42000: Can't group on 'sq' SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; -sq -3 +ERROR 42000: Can't group on 'sq' SELECT * FROM v2 where ( SELECT MIN(v2.f2) FROM t1 ) > 0; f2 3 @@ -7146,9 +7147,10 @@ SELECT count(*) FROM v2 group by ( SELECT MIN(v2.f2) FROM t1 ); count(*) 1 delete from t1; +SELECT ( SELECT MIN(t2.f2) FROM t1 ) AS sq FROM t2 GROUP BY sq; +ERROR 42000: Can't group on 'sq' SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; -sq -NULL +ERROR 42000: Can't group on 'sq' drop view v2; drop table t1,t2; # @@ -7163,6 +7165,29 @@ f1 f2 foo bar DROP TABLE t1; # +# MDEV-10146: Wrong result (or questionable result and behavior) +# with aggregate function in uncorrelated SELECT subquery +# +CREATE TABLE t1 (f1 INT); +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (f2 int); +INSERT INTO t2 VALUES (3); +SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1; +( SELECT MAX(f1) FROM t2 ) +2 +SELECT ( SELECT MAX(f1) FROM t2 ) FROM v1; +( SELECT MAX(f1) FROM t2 ) +2 +INSERT INTO t2 VALUES (4); +SELECT ( SELECT MAX(f1) FROM t2 ) FROM v1; +ERROR 21000: Subquery returns more than 1 row +SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1; +ERROR 21000: Subquery returns more than 1 row +drop view v1; +drop table t1,t2; +# End of 10.0 tests +# # MDEV-9487: Server crashes in Time_and_counter_tracker::incr_loops # with UNION in ALL subquery # @@ -7189,6 +7214,6 @@ SELECT * FROM t1, t2 WHERE f3 = f2 AND f1 > ANY ( SELECT 'foo'); f1 f2 f3 DROP TABLE t1, t2; SET NAMES default; -End of 10.1 tests +# End of 10.1 tests set @optimizer_switch_for_subselect_test=null; set @join_cache_level_for_subselect_test=NULL; diff --git a/mysql-test/suite/parts/r/longname.result b/mysql-test/suite/parts/r/longname.result new file mode 100644 index 00000000000..6424ba28297 --- /dev/null +++ b/mysql-test/suite/parts/r/longname.result @@ -0,0 +1,37 @@ +set names utf8; +create database mysqltest1; +select database_name, table_name, length(table_name) from mysql.innodb_table_stats where database_name = 'mysqltest1'; +database_name table_name length(table_name) +CREATE TABLE mysqltest1.test_jfg_table_name_with_64_chars_123456789012345678901234567890 ( +id int(10) unsigned NOT NULL, +id2 int(10) unsigned NOT NULL, +PRIMARY KEY ( id, id2 ) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +PARTITION BY RANGE ( id ) +SUBPARTITION BY HASH ( id2 ) +SUBPARTITIONS 2 ( +PARTITION test_jfg_partition_name_with_60_chars_1234567890123456789012 VALUES LESS THAN (1000) ENGINE = InnoDB, +PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = InnoDB); +Warnings: +Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope. +Warning 1478 InnoDB: assuming ROW_FORMAT=COMPACT. +Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope. +Warning 1478 InnoDB: assuming ROW_FORMAT=COMPACT. +Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope. +Warning 1478 InnoDB: assuming ROW_FORMAT=COMPACT. +Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope. +Warning 1478 InnoDB: assuming ROW_FORMAT=COMPACT. +select database_name, table_name, length(table_name) from mysql.innodb_table_stats where database_name = 'mysqltest1'; +database_name table_name length(table_name) +CREATE TABLE mysqltest1.éééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééé ( +id int(10) unsigned NOT NULL, +id2 int(10) unsigned NOT NULL, +PRIMARY KEY ( id, id2 ) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +PARTITION BY RANGE ( id ) +SUBPARTITION BY HASH ( id2 ) +SUBPARTITIONS 2 ( +PARTITION çççççççççççççççççççççççççççççççççççççççççççççççççççççççççççç VALUES LESS THAN (1000) ENGINE = InnoDB, +PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = InnoDB); +ERROR HY000: The path specified for @0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@0n@ is too long. +drop database mysqltest1; diff --git a/mysql-test/suite/parts/t/longname.test b/mysql-test/suite/parts/t/longname.test new file mode 100644 index 00000000000..0f7378ef8e3 --- /dev/null +++ b/mysql-test/suite/parts/t/longname.test @@ -0,0 +1,32 @@ +source include/have_innodb.inc; +source include/have_partition.inc; +set names utf8; + +create database mysqltest1; +select database_name, table_name, length(table_name) from mysql.innodb_table_stats where database_name = 'mysqltest1'; +CREATE TABLE mysqltest1.test_jfg_table_name_with_64_chars_123456789012345678901234567890 ( + id int(10) unsigned NOT NULL, + id2 int(10) unsigned NOT NULL, + PRIMARY KEY ( id, id2 ) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +PARTITION BY RANGE ( id ) + SUBPARTITION BY HASH ( id2 ) + SUBPARTITIONS 2 ( + PARTITION test_jfg_partition_name_with_60_chars_1234567890123456789012 VALUES LESS THAN (1000) ENGINE = InnoDB, + PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = InnoDB); + +select database_name, table_name, length(table_name) from mysql.innodb_table_stats where database_name = 'mysqltest1'; + +--error ER_PATH_LENGTH +CREATE TABLE mysqltest1.éééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééé ( + id int(10) unsigned NOT NULL, + id2 int(10) unsigned NOT NULL, + PRIMARY KEY ( id, id2 ) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +PARTITION BY RANGE ( id ) + SUBPARTITION BY HASH ( id2 ) + SUBPARTITIONS 2 ( + PARTITION çççççççççççççççççççççççççççççççççççççççççççççççççççççççççççç VALUES LESS THAN (1000) ENGINE = InnoDB, + PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = InnoDB); + +drop database mysqltest1; diff --git a/mysql-test/suite/rpl/r/circular_serverid0.result b/mysql-test/suite/rpl/r/circular_serverid0.result new file mode 100644 index 00000000000..899b4bd343b --- /dev/null +++ b/mysql-test/suite/rpl/r/circular_serverid0.result @@ -0,0 +1,30 @@ +include/rpl_init.inc [topology=1->2->1] +include/rpl_connect.inc [creating M4] +include/rpl_connect.inc [creating M2] +SET @old_debug= @@global.debug; +STOP SLAVE; +SET GLOBAL debug_dbug= "+d,dbug.rows_events_to_delay_relay_logging"; +START SLAVE IO_THREAD; +include/wait_for_slave_io_to_start.inc +CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b VARCHAR(30000)) ENGINE=innodb; +INSERT INTO `t1` VALUES (null, repeat('a', 1024)), (null, repeat('b', 1024)); +SET debug_sync='now WAIT_FOR start_sql_thread'; +START SLAVE SQL_THREAD; +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +slave-bin.000001 # Gtid # # GTID #-#-# +slave-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b VARCHAR(30000)) ENGINE=innodb +SET debug_sync='now SIGNAL go_on_relay_logging'; +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +slave-bin.000001 # Gtid # # GTID #-#-# +slave-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b VARCHAR(30000)) ENGINE=innodb +slave-bin.000001 # Gtid # # BEGIN GTID #-#-# +slave-bin.000001 # Table_map # # table_id: # (test.t1) +slave-bin.000001 # Write_rows_v1 # # table_id: # +slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F +slave-bin.000001 # Xid # # COMMIT /* XID */ +drop table t1; +SET GLOBAL debug_dbug= @old_debug; +SET debug_sync='RESET'; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/circular_serverid0.cnf b/mysql-test/suite/rpl/t/circular_serverid0.cnf new file mode 100644 index 00000000000..277aac2869b --- /dev/null +++ b/mysql-test/suite/rpl/t/circular_serverid0.cnf @@ -0,0 +1,30 @@ +!include ../my.cnf + +[mysqld.1] +gtid-domain-id=4 +server-id=4 +# +log-slave-updates +slave-parallel-threads=0 +gtid-strict-mode=1 +gtid-ignore-duplicates=1 + +# +# Max-size row events to minimum with the idea to create +# a number of Rows_log_event per Query. +# +binlog-row-event-max-size=1024 + +[mysqld.2] +gtid-domain-id=2 +server-id=2 +# +log-slave-updates +slave-parallel-threads=0 +gtid-strict-mode=1 +gtid-ignore-duplicates=1 +binlog-row-event-max-size=1024 +# The slave will be initialized with a @@global.dbug-var value +skip-slave-start=1 + + diff --git a/mysql-test/suite/rpl/t/circular_serverid0.test b/mysql-test/suite/rpl/t/circular_serverid0.test new file mode 100644 index 00000000000..20ad58e2c52 --- /dev/null +++ b/mysql-test/suite/rpl/t/circular_serverid0.test @@ -0,0 +1,104 @@ +# +# Testing chain/circular replication scenario of MDEV-9670 +# The effect of the bug was that we got a commit with a GTID with server_id +# + +--source include/have_binlog_format_row.inc +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +--let $rpl_topology= 1->2->1 +--source include/rpl_init.inc + +--let $rpl_connection_name= M4 +--let $rpl_server_number= 1 +--source include/rpl_connect.inc + +--let $rpl_connection_name= M2 +--let $rpl_server_number= 2 +--source include/rpl_connect.inc + +# The parameter reflects binlog-row-event-max-size @cnf. +--let $row_size=1024 + +SET @old_debug= @@global.debug; + +--connection M2 +STOP SLAVE; +SET GLOBAL debug_dbug= "+d,dbug.rows_events_to_delay_relay_logging"; +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc + +--connection M2 +# This query also creates a Gtid event group whose Gtid will remain in +# ignored status for too long causing a following group split. + +CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b VARCHAR(30000)) ENGINE=innodb; +--sync_slave_with_master M4 + +# This INSERT will be logged as two Write_log events which the buggy +# slave applier would split. + +--connection M4 +eval INSERT INTO `t1` VALUES (null, repeat('a', $row_size)), (null, repeat('b', $row_size)); + +# START M2 IO thread and wait for its signal to follow with the SQL +# thread start. At this moment the SQL thread shall be having 2 and +# "half" groups to execute. The "hafl" one would be committed by the +# buggy applier after which the IO is released to queue the rest of +# the 3rd group which the SQL thread commits separately to complete +# the split. + +--connection M2 + +# wait for IO signal to start the SQL thread. IO will be hanging upon that. +SET debug_sync='now WAIT_FOR start_sql_thread'; + +# Now the slave server has relay log whose last group is incomplete. +# An unfixed slave server would go to "insert" a "fake" +# Gtid_list_log_event event which actually would commit the incomplete +# group. However before to actual commit do_apply_event() hits some assert. +# In the fixed server the fake Gtid_list_log_event is *not* inserted +# in the middle of a group. +START SLAVE SQL_THREAD; + +# Sleep for a little time to give SQL thread a chance to commit while +# the IO thread is hanging (see +# DBUG_EXECUTE_IF("dbug.rows_events_to_delay_relay_logging"...) in +# queue_event). Alternatively to reproduce the case when buggy slave +# wait for the 1st group commit + +#--let $count= 1 +#--let $table= t1 +#--source include/wait_until_rows_count.inc + +--sleep 2 + +# Demonstrate either no split group in the correct slave or the 1nd +# group in the buggy one +--source include/show_binlog_events.inc + +# Release the IO thread +SET debug_sync='now SIGNAL go_on_relay_logging'; + +# Sync servers +--sync_slave_with_master M4 +--connection M4 +--sync_slave_with_master M2 +--connection M2 + +# Demonstrate replication goes correctly not to create any split, or +# the 2nd group in the buggy slave +--source include/show_binlog_events.inc + +# +# Cleanup +# +--connection M4 +drop table t1; + +--connection M2 +SET GLOBAL debug_dbug= @old_debug; +SET debug_sync='RESET'; +--source include/rpl_end.inc diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index cfb5042299a..bc84b6b9e26 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3600,7 +3600,7 @@ SET SESSION sql_mode=@old_sql_mode; drop table t2, t1; drop view v1; ---echo End of 5.0 tests. +--echo # End of 5.0 tests. # # Test [NOT] IN truth table (both as top-level and general predicate). @@ -4685,7 +4685,7 @@ select * from t2 where a=(select a from t1) and a='x'; drop table t1,t2; ---echo End of 5.1 tests +--echo # End of 5.1 tests --echo # --echo # Bug #11765713 58705: @@ -5156,7 +5156,7 @@ eval SELECT * FROM ( $subq ) AS alias3; DROP TABLE t1,t2; ---echo End of 5.2 tests +--echo # End of 5.2 tests --echo # --echo # BUG#779885: Crash in eliminate_item_equal with materialization=on in @@ -6004,11 +6004,17 @@ INSERT INTO t2 VALUES (3); CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t2; +--error ER_WRONG_GROUP_FIELD +SELECT ( SELECT MIN(t2.f2) FROM t1 ) AS sq FROM t2 GROUP BY sq; +--error ER_WRONG_GROUP_FIELD SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; SELECT * FROM v2 where ( SELECT MIN(v2.f2) FROM t1 ) > 0; SELECT count(*) FROM v2 group by ( SELECT MIN(v2.f2) FROM t1 ); delete from t1; +--error ER_WRONG_GROUP_FIELD +SELECT ( SELECT MIN(t2.f2) FROM t1 ) AS sq FROM t2 GROUP BY sq; +--error ER_WRONG_GROUP_FIELD SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; drop view v2; @@ -6024,6 +6030,32 @@ SELECT * FROM t1 WHERE f2 >= SOME ( SELECT f1 FROM t1 ); SELECT * FROM t1 WHERE f2 <= SOME ( SELECT f1 FROM t1 ); DROP TABLE t1; +--echo # +--echo # MDEV-10146: Wrong result (or questionable result and behavior) +--echo # with aggregate function in uncorrelated SELECT subquery +--echo # +CREATE TABLE t1 (f1 INT); +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (1),(2); + +CREATE TABLE t2 (f2 int); + +INSERT INTO t2 VALUES (3); +SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1; + +SELECT ( SELECT MAX(f1) FROM t2 ) FROM v1; + +INSERT INTO t2 VALUES (4); + +--error ER_SUBQUERY_NO_1_ROW +SELECT ( SELECT MAX(f1) FROM t2 ) FROM v1; +--error ER_SUBQUERY_NO_1_ROW +SELECT ( SELECT MAX(f1) FROM t2 ) FROM t1; + +drop view v1; +drop table t1,t2; + +--echo # End of 10.0 tests --echo # --echo # MDEV-9487: Server crashes in Time_and_counter_tracker::incr_loops @@ -6051,4 +6083,4 @@ SELECT * FROM t1, t2 WHERE f3 = f2 AND f1 > ANY ( SELECT 'foo'); DROP TABLE t1, t2; SET NAMES default; ---echo End of 10.1 tests +--echo # End of 10.1 tests diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 29054c76cbe..8ebc11252e1 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -674,7 +674,7 @@ int ha_partition::create(const char *name, TABLE *table_arg, HA_CREATE_INFO *create_info) { int error; - char name_buff[FN_REFLEN], name_lc_buff[FN_REFLEN]; + char name_buff[FN_REFLEN + 1], name_lc_buff[FN_REFLEN]; char *name_buffer_ptr; const char *path; uint i; @@ -716,8 +716,9 @@ int ha_partition::create(const char *name, TABLE *table_arg, for (j= 0; j < m_part_info->num_subparts; j++) { part_elem= sub_it++; - create_partition_name(name_buff, path, name_buffer_ptr, - NORMAL_PART_NAME, FALSE); + if ((error= create_partition_name(name_buff, sizeof(name_buff), path, + name_buffer_ptr, NORMAL_PART_NAME, FALSE))) + goto create_error; if ((error= set_up_table_before_create(table_arg, name_buff, create_info, part_elem)) || ((error= (*file)->ha_create(name_buff, table_arg, create_info)))) @@ -729,8 +730,9 @@ int ha_partition::create(const char *name, TABLE *table_arg, } else { - create_partition_name(name_buff, path, name_buffer_ptr, - NORMAL_PART_NAME, FALSE); + if ((error= create_partition_name(name_buff, sizeof(name_buff), path, + name_buffer_ptr, NORMAL_PART_NAME, FALSE))) + goto create_error; if ((error= set_up_table_before_create(table_arg, name_buff, create_info, part_elem)) || ((error= (*file)->ha_create(name_buff, table_arg, create_info)))) @@ -746,9 +748,9 @@ create_error: name_buffer_ptr= m_name_buffer_ptr; for (abort_file= file, file= m_file; file < abort_file; file++) { - create_partition_name(name_buff, path, name_buffer_ptr, NORMAL_PART_NAME, - FALSE); - (void) (*file)->ha_delete_table((const char*) name_buff); + if (!create_partition_name(name_buff, sizeof(name_buff), path, + name_buffer_ptr, NORMAL_PART_NAME, FALSE)) + (void) (*file)->ha_delete_table((const char*) name_buff); name_buffer_ptr= strend(name_buffer_ptr) + 1; } handler::delete_table(name); @@ -775,7 +777,7 @@ create_error: int ha_partition::drop_partitions(const char *path) { List_iterator<partition_element> part_it(m_part_info->partitions); - char part_name_buff[FN_REFLEN]; + char part_name_buff[FN_REFLEN + 1]; uint num_parts= m_part_info->partitions.elements; uint num_subparts= m_part_info->num_subparts; uint i= 0; @@ -808,9 +810,11 @@ int ha_partition::drop_partitions(const char *path) { partition_element *sub_elem= sub_it++; part= i * num_subparts + j; - create_subpartition_name(part_name_buff, path, - part_elem->partition_name, - sub_elem->partition_name, name_variant); + if ((ret_error= create_subpartition_name(part_name_buff, + sizeof(part_name_buff), path, + part_elem->partition_name, + sub_elem->partition_name, name_variant))) + error= ret_error; file= m_file[part]; DBUG_PRINT("info", ("Drop subpartition %s", part_name_buff)); if ((ret_error= file->ha_delete_table(part_name_buff))) @@ -821,15 +825,19 @@ int ha_partition::drop_partitions(const char *path) } else { - create_partition_name(part_name_buff, path, - part_elem->partition_name, name_variant, - TRUE); - file= m_file[i]; - DBUG_PRINT("info", ("Drop partition %s", part_name_buff)); - if ((ret_error= file->ha_delete_table(part_name_buff))) + if ((ret_error= create_partition_name(part_name_buff, + sizeof(part_name_buff), path, + part_elem->partition_name, name_variant, TRUE))) error= ret_error; - if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos)) - error= 1; + else + { + file= m_file[i]; + DBUG_PRINT("info", ("Drop partition %s", part_name_buff)); + if ((ret_error= file->ha_delete_table(part_name_buff))) + error= ret_error; + if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos)) + error= 1; + } } if (part_elem->part_state == PART_IS_CHANGED) part_elem->part_state= PART_NORMAL; @@ -865,8 +873,8 @@ int ha_partition::rename_partitions(const char *path) { List_iterator<partition_element> part_it(m_part_info->partitions); List_iterator<partition_element> temp_it(m_part_info->temp_partitions); - char part_name_buff[FN_REFLEN]; - char norm_name_buff[FN_REFLEN]; + char part_name_buff[FN_REFLEN + 1]; + char norm_name_buff[FN_REFLEN + 1]; uint num_parts= m_part_info->partitions.elements; uint part_count= 0; uint num_subparts= m_part_info->num_subparts; @@ -908,10 +916,11 @@ int ha_partition::rename_partitions(const char *path) { sub_elem= sub_it++; file= m_reorged_file[part_count++]; - create_subpartition_name(norm_name_buff, path, - part_elem->partition_name, - sub_elem->partition_name, - NORMAL_PART_NAME); + if ((ret_error= create_subpartition_name(norm_name_buff, + sizeof(norm_name_buff), path, + part_elem->partition_name, + sub_elem->partition_name, NORMAL_PART_NAME))) + error= ret_error; DBUG_PRINT("info", ("Delete subpartition %s", norm_name_buff)); if ((ret_error= file->ha_delete_table(norm_name_buff))) error= ret_error; @@ -924,16 +933,20 @@ int ha_partition::rename_partitions(const char *path) else { file= m_reorged_file[part_count++]; - create_partition_name(norm_name_buff, path, - part_elem->partition_name, NORMAL_PART_NAME, - TRUE); - DBUG_PRINT("info", ("Delete partition %s", norm_name_buff)); - if ((ret_error= file->ha_delete_table(norm_name_buff))) + if ((ret_error= create_partition_name(norm_name_buff, + sizeof(norm_name_buff), path, + part_elem->partition_name, NORMAL_PART_NAME, TRUE))) error= ret_error; - else if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos)) - error= 1; else - part_elem->log_entry= NULL; /* Indicate success */ + { + DBUG_PRINT("info", ("Delete partition %s", norm_name_buff)); + if ((ret_error= file->ha_delete_table(norm_name_buff))) + error= ret_error; + else if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos)) + error= 1; + else + part_elem->log_entry= NULL; /* Indicate success */ + } } } while (++i < temp_partitions); (void) sync_ddl_log(); @@ -976,10 +989,11 @@ int ha_partition::rename_partitions(const char *path) { sub_elem= sub_it++; part= i * num_subparts + j; - create_subpartition_name(norm_name_buff, path, - part_elem->partition_name, - sub_elem->partition_name, - NORMAL_PART_NAME); + if ((ret_error= create_subpartition_name(norm_name_buff, + sizeof(norm_name_buff), path, + part_elem->partition_name, + sub_elem->partition_name, NORMAL_PART_NAME))) + error= ret_error; if (part_elem->part_state == PART_IS_CHANGED) { file= m_reorged_file[part_count++]; @@ -991,10 +1005,11 @@ int ha_partition::rename_partitions(const char *path) (void) sync_ddl_log(); } file= m_new_file[part]; - create_subpartition_name(part_name_buff, path, - part_elem->partition_name, - sub_elem->partition_name, - TEMP_PART_NAME); + if ((ret_error= create_subpartition_name(part_name_buff, + sizeof(part_name_buff), path, + part_elem->partition_name, + sub_elem->partition_name, TEMP_PART_NAME))) + error= ret_error; DBUG_PRINT("info", ("Rename subpartition from %s to %s", part_name_buff, norm_name_buff)); if ((ret_error= file->ha_rename_table(part_name_buff, @@ -1008,32 +1023,36 @@ int ha_partition::rename_partitions(const char *path) } else { - create_partition_name(norm_name_buff, path, - part_elem->partition_name, NORMAL_PART_NAME, - TRUE); - if (part_elem->part_state == PART_IS_CHANGED) + if ((ret_error= create_partition_name(norm_name_buff, + sizeof(norm_name_buff), path, + part_elem->partition_name, NORMAL_PART_NAME, TRUE)) || + (ret_error= create_partition_name(part_name_buff, + sizeof(part_name_buff), path, + part_elem->partition_name, TEMP_PART_NAME, TRUE))) + error= ret_error; + else { - file= m_reorged_file[part_count++]; - DBUG_PRINT("info", ("Delete partition %s", norm_name_buff)); - if ((ret_error= file->ha_delete_table(norm_name_buff))) + if (part_elem->part_state == PART_IS_CHANGED) + { + file= m_reorged_file[part_count++]; + DBUG_PRINT("info", ("Delete partition %s", norm_name_buff)); + if ((ret_error= file->ha_delete_table(norm_name_buff))) + error= ret_error; + else if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos)) + error= 1; + (void) sync_ddl_log(); + } + file= m_new_file[i]; + DBUG_PRINT("info", ("Rename partition from %s to %s", + part_name_buff, norm_name_buff)); + if ((ret_error= file->ha_rename_table(part_name_buff, + norm_name_buff))) error= ret_error; else if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos)) error= 1; - (void) sync_ddl_log(); + else + part_elem->log_entry= NULL; } - file= m_new_file[i]; - create_partition_name(part_name_buff, path, - part_elem->partition_name, TEMP_PART_NAME, - TRUE); - DBUG_PRINT("info", ("Rename partition from %s to %s", - part_name_buff, norm_name_buff)); - if ((ret_error= file->ha_rename_table(part_name_buff, - norm_name_buff))) - error= ret_error; - else if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos)) - error= 1; - else - part_elem->log_entry= NULL; } } } while (++i < num_parts); @@ -1649,7 +1668,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, { List_iterator<partition_element> part_it(m_part_info->partitions); List_iterator <partition_element> t_it(m_part_info->temp_partitions); - char part_name_buff[FN_REFLEN]; + char part_name_buff[FN_REFLEN + 1]; uint num_parts= m_part_info->partitions.elements; uint num_subparts= m_part_info->num_subparts; uint i= 0; @@ -1878,10 +1897,14 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, do { partition_element *sub_elem= sub_it++; - create_subpartition_name(part_name_buff, path, - part_elem->partition_name, - sub_elem->partition_name, - name_variant); + if ((error= create_subpartition_name(part_name_buff, + sizeof(part_name_buff), path, + part_elem->partition_name, sub_elem->partition_name, + name_variant))) + { + cleanup_new_partition(part_count); + DBUG_RETURN(error); + } part= i * num_subparts + j; DBUG_PRINT("info", ("Add subpartition %s", part_name_buff)); if ((error= prepare_new_partition(table, create_info, @@ -1899,9 +1922,14 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, } else { - create_partition_name(part_name_buff, path, - part_elem->partition_name, name_variant, - TRUE); + if ((error= create_partition_name(part_name_buff, + sizeof(part_name_buff), path, part_elem->partition_name, + name_variant, TRUE))) + { + cleanup_new_partition(part_count); + DBUG_RETURN(error); + } + DBUG_PRINT("info", ("Add partition %s", part_name_buff)); if ((error= prepare_new_partition(table, create_info, new_file_array[i], @@ -2272,8 +2300,8 @@ uint ha_partition::del_ren_table(const char *from, const char *to) { int save_error= 0; int error; - char from_buff[FN_REFLEN], to_buff[FN_REFLEN], from_lc_buff[FN_REFLEN], - to_lc_buff[FN_REFLEN]; + char from_buff[FN_REFLEN + 1], to_buff[FN_REFLEN + 1], + from_lc_buff[FN_REFLEN], to_lc_buff[FN_REFLEN]; char *name_buffer_ptr; const char *from_path; const char *to_path= NULL; @@ -2309,13 +2337,15 @@ uint ha_partition::del_ren_table(const char *from, const char *to) i= 0; do { - create_partition_name(from_buff, from_path, name_buffer_ptr, - NORMAL_PART_NAME, FALSE); + if ((error= create_partition_name(from_buff, sizeof(from_buff), from_path, + name_buffer_ptr, NORMAL_PART_NAME, FALSE))) + goto rename_error; if (to != NULL) { // Rename branch - create_partition_name(to_buff, to_path, name_buffer_ptr, - NORMAL_PART_NAME, FALSE); + if ((error= create_partition_name(to_buff, sizeof(to_buff), to_path, + name_buffer_ptr, NORMAL_PART_NAME, FALSE))) + goto rename_error; error= (*file)->ha_rename_table(from_buff, to_buff); if (error) goto rename_error; @@ -2344,12 +2374,14 @@ rename_error: for (abort_file= file, file= m_file; file < abort_file; file++) { /* Revert the rename, back from 'to' to the original 'from' */ - create_partition_name(from_buff, from_path, name_buffer_ptr, - NORMAL_PART_NAME, FALSE); - create_partition_name(to_buff, to_path, name_buffer_ptr, - NORMAL_PART_NAME, FALSE); - /* Ignore error here */ - (void) (*file)->ha_rename_table(to_buff, from_buff); + if (!create_partition_name(from_buff, sizeof(from_buff), from_path, + name_buffer_ptr, NORMAL_PART_NAME, FALSE) && + !create_partition_name(to_buff, sizeof(to_buff), to_path, + name_buffer_ptr, NORMAL_PART_NAME, FALSE)) + { + /* Ignore error here */ + (void) (*file)->ha_rename_table(to_buff, from_buff); + } name_buffer_ptr= strend(name_buffer_ptr) + 1; } DBUG_RETURN(error); @@ -3416,7 +3448,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) char *name_buffer_ptr; int error= HA_ERR_INITIALIZATION; handler **file; - char name_buff[FN_REFLEN]; + char name_buff[FN_REFLEN + 1]; ulonglong check_table_flags; DBUG_ENTER("ha_partition::open"); @@ -3470,8 +3502,9 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) file= m_is_clone_of->m_file; for (i= 0; i < m_tot_parts; i++) { - create_partition_name(name_buff, name, name_buffer_ptr, NORMAL_PART_NAME, - FALSE); + if ((error= create_partition_name(name_buff, sizeof(name_buff), name, + name_buffer_ptr, NORMAL_PART_NAME, FALSE))) + goto err_handler; /* ::clone() will also set ha_share from the original. */ if (!(m_file[i]= file[i]->clone(name_buff, m_clone_mem_root))) { @@ -3487,8 +3520,9 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) file= m_file; do { - create_partition_name(name_buff, name, name_buffer_ptr, NORMAL_PART_NAME, - FALSE); + if ((error= create_partition_name(name_buff, sizeof(name_buff), name, + name_buffer_ptr, NORMAL_PART_NAME, FALSE))) + goto err_handler; table->s->connect_string = m_connect_string[(uint)(file-m_file)]; if ((error= (*file)->ha_open(table, name_buff, mode, test_if_locked | HA_OPEN_NO_PSI_CALL))) diff --git a/sql/item.cc b/sql/item.cc index 631ecb44b30..82b7cacbabb 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4875,6 +4875,12 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) ((ref_type == REF_ITEM || ref_type == FIELD_ITEM) ? (Item_ident*) (*reference) : 0)); + if (thd->lex->in_sum_func && + thd->lex->in_sum_func->nest_level >= select->nest_level) + { + set_if_bigger(thd->lex->in_sum_func->max_arg_level, + select->nest_level); + } /* A reference to a view field had been found and we substituted it instead of this Item (find_field_in_tables diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 49bf8036ea1..fa74a1903da 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -3100,7 +3100,7 @@ get_date_time_result_type(const char *format, uint length) const char *val= format; const char *end= format + length; - for (; val != end && val != end; val++) + for (; val != end; val++) { if (*val == '%' && val+1 != end) { diff --git a/sql/partition_info.cc b/sql/partition_info.cc index bc0db9e0174..cd0ab970d76 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -889,6 +889,7 @@ char* partition_info::find_duplicate_field() */ partition_element *partition_info::get_part_elem(const char *partition_name, char *file_name, + size_t file_name_size, uint32 *part_id) { List_iterator<partition_element> part_it(partitions); @@ -910,10 +911,10 @@ partition_element *partition_info::get_part_elem(const char *partition_name, sub_part_elem->partition_name, partition_name)) { if (file_name) - create_subpartition_name(file_name, "", - part_elem->partition_name, - partition_name, - NORMAL_PART_NAME); + if (create_subpartition_name(file_name, file_name_size, "", + part_elem->partition_name, + partition_name, NORMAL_PART_NAME)) + DBUG_RETURN(NULL); *part_id= j + (i * num_subparts); DBUG_RETURN(sub_part_elem); } @@ -928,8 +929,9 @@ partition_element *partition_info::get_part_elem(const char *partition_name, part_elem->partition_name, partition_name)) { if (file_name) - create_partition_name(file_name, "", partition_name, - NORMAL_PART_NAME, TRUE); + if (create_partition_name(file_name, file_name_size, "", + partition_name, NORMAL_PART_NAME, TRUE)) + DBUG_RETURN(NULL); *part_id= i; DBUG_RETURN(part_elem); } diff --git a/sql/partition_info.h b/sql/partition_info.h index df7010b2ab3..ec7374b3e3e 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -340,9 +340,8 @@ public: bool init_column_part(THD *thd); bool add_column_list_value(THD *thd, Item *item); void set_show_version_string(String *packet); - partition_element *get_part_elem(const char *partition_name, - char *file_name, - uint32 *part_id); + partition_element *get_part_elem(const char *partition_name, char *file_name, + size_t file_name_size, uint32 *part_id); void report_part_expr_error(bool use_subpart_expr); bool set_used_partition(List<Item> &fields, List<Item> &values, diff --git a/sql/slave.cc b/sql/slave.cc index a6169003f4e..d87ac0e6ba3 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2466,6 +2466,7 @@ static void write_ignored_events_info_to_relay_log(THD *thd, Master_info *mi) } if (rli->ign_gtids.count()) { + DBUG_ASSERT(!rli->is_in_group()); // Ensure no active transaction glev= new Gtid_list_log_event(&rli->ign_gtids, Gtid_list_log_event::FLAG_IGN_GTIDS); rli->ign_gtids.reset(); @@ -5582,7 +5583,9 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) bool gtid_skip_enqueue= false; bool got_gtid_event= false; rpl_gtid event_gtid; - +#ifndef DBUG_OFF + static uint dbug_rows_event_count= 0; +#endif /* FD_q must have been prepared for the first R_a event inside get_master_version_and_clock() @@ -5649,6 +5652,26 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) (uchar)buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT /* a way to escape */) DBUG_RETURN(queue_old_event(mi,buf,event_len)); +#ifdef ENABLED_DEBUG_SYNC + /* + A (+d,dbug.rows_events_to_delay_relay_logging)-test is supposed to + create a few Write_log_events and after receiving the 1st of them + the IO thread signals to launch the SQL thread, and sets itself to + wait for a release signal. + */ + DBUG_EXECUTE_IF("dbug.rows_events_to_delay_relay_logging", + if ((buf[EVENT_TYPE_OFFSET] == WRITE_ROWS_EVENT_V1 || + buf[EVENT_TYPE_OFFSET] == WRITE_ROWS_EVENT) && + ++dbug_rows_event_count == 2) + { + const char act[]= + "now SIGNAL start_sql_thread " + "WAIT_FOR go_on_relay_logging"; + DBUG_ASSERT(debug_sync_service); + DBUG_ASSERT(!debug_sync_set_action(current_thd, + STRING_WITH_LEN(act))); + };); +#endif mysql_mutex_lock(&mi->data_lock); switch ((uchar)buf[EVENT_TYPE_OFFSET]) { @@ -6897,9 +6920,12 @@ static Log_event* next_event(rpl_group_info *rgi, ulonglong *event_size) DBUG_RETURN(ev); } - if (rli->ign_gtids.count()) + if (rli->ign_gtids.count() && !rli->is_in_group()) { - /* We generate and return a Gtid_list, to update gtid_slave_pos. */ + /* + We generate and return a Gtid_list, to update gtid_slave_pos, + unless being in the middle of a group. + */ DBUG_PRINT("info",("seeing ignored end gtids")); ev= new Gtid_list_log_event(&rli->ign_gtids, Gtid_list_log_event::FLAG_IGN_GTIDS); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index f2a60bbd500..78b8b3f05eb 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -4113,7 +4113,7 @@ void Security_context::destroy() if (external_user) { my_free(external_user); - user= NULL; + external_user= NULL; } my_free(ip); @@ -4330,6 +4330,10 @@ extern "C" enum thd_kill_levels thd_kill_level(const MYSQL_THD thd) however not more often than global.progress_report_time. If global.progress_report_time is 0, then don't send progress reports, but check every second if the value has changed + + We clear any errors that we get from sending the progress packet to + the client as we don't want to set an error without the caller knowing + about it. */ static void thd_send_progress(THD *thd) @@ -4346,8 +4350,12 @@ static void thd_send_progress(THD *thd) thd->progress.next_report_time= (report_time + seconds_to_next * 1000000000ULL); if (global_system_variables.progress_report_time && - thd->variables.progress_report_time) + thd->variables.progress_report_time && !thd->is_error()) + { net_send_progress_packet(thd); + if (thd->is_error()) + thd->clear_error(); + } } } diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index ea79d941f13..78f8518650f 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -5989,8 +5989,8 @@ static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, DDL_LOG_ENTRY ddl_log_entry; partition_info *part_info= lpt->part_info; DDL_LOG_MEMORY_ENTRY *log_entry; - char tmp_path[FN_REFLEN]; - char normal_path[FN_REFLEN]; + char tmp_path[FN_REFLEN + 1]; + char normal_path[FN_REFLEN + 1]; List_iterator<partition_element> part_it(part_info->partitions); uint temp_partitions= part_info->temp_partitions.elements; uint num_elements= part_info->partitions.elements; @@ -6014,14 +6014,15 @@ static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, ddl_log_entry.next_entry= *next_entry; ddl_log_entry.handler_name= ha_resolve_storage_engine_name(sub_elem->engine_type); - create_subpartition_name(tmp_path, path, - part_elem->partition_name, - sub_elem->partition_name, - TEMP_PART_NAME); - create_subpartition_name(normal_path, path, - part_elem->partition_name, - sub_elem->partition_name, - NORMAL_PART_NAME); + if (create_subpartition_name(tmp_path, sizeof(tmp_path), path, + part_elem->partition_name, + sub_elem->partition_name, + TEMP_PART_NAME) || + create_subpartition_name(normal_path, sizeof(normal_path), path, + part_elem->partition_name, + sub_elem->partition_name, + NORMAL_PART_NAME)) + DBUG_RETURN(TRUE); ddl_log_entry.name= normal_path; ddl_log_entry.from_name= tmp_path; if (part_elem->part_state == PART_IS_CHANGED) @@ -6042,12 +6043,13 @@ static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, ddl_log_entry.next_entry= *next_entry; ddl_log_entry.handler_name= ha_resolve_storage_engine_name(part_elem->engine_type); - create_partition_name(tmp_path, path, - part_elem->partition_name, - TEMP_PART_NAME, TRUE); - create_partition_name(normal_path, path, - part_elem->partition_name, - NORMAL_PART_NAME, TRUE); + if (create_partition_name(tmp_path, sizeof(tmp_path), path, + part_elem->partition_name, TEMP_PART_NAME, + TRUE) || + create_partition_name(normal_path, sizeof(normal_path), path, + part_elem->partition_name, NORMAL_PART_NAME, + TRUE)) + DBUG_RETURN(TRUE); ddl_log_entry.name= normal_path; ddl_log_entry.from_name= tmp_path; if (part_elem->part_state == PART_IS_CHANGED) @@ -6086,7 +6088,7 @@ static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, DDL_LOG_ENTRY ddl_log_entry; partition_info *part_info= lpt->part_info; DDL_LOG_MEMORY_ENTRY *log_entry; - char tmp_path[FN_LEN]; + char tmp_path[FN_REFLEN + 1]; List_iterator<partition_element> part_it(part_info->partitions); List_iterator<partition_element> temp_it(part_info->temp_partitions); uint num_temp_partitions= part_info->temp_partitions.elements; @@ -6125,10 +6127,10 @@ static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, ddl_log_entry.next_entry= *next_entry; ddl_log_entry.handler_name= ha_resolve_storage_engine_name(sub_elem->engine_type); - create_subpartition_name(tmp_path, path, - part_elem->partition_name, - sub_elem->partition_name, - name_variant); + if (create_subpartition_name(tmp_path, sizeof(tmp_path), path, + part_elem->partition_name, + sub_elem->partition_name, name_variant)) + DBUG_RETURN(TRUE); ddl_log_entry.name= tmp_path; if (write_ddl_log_entry(&ddl_log_entry, &log_entry)) { @@ -6144,9 +6146,10 @@ static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt, ddl_log_entry.next_entry= *next_entry; ddl_log_entry.handler_name= ha_resolve_storage_engine_name(part_elem->engine_type); - create_partition_name(tmp_path, path, - part_elem->partition_name, - name_variant, TRUE); + if (create_partition_name(tmp_path, sizeof(tmp_path), path, + part_elem->partition_name, name_variant, + TRUE)) + DBUG_RETURN(TRUE); ddl_log_entry.name= tmp_path; if (write_ddl_log_entry(&ddl_log_entry, &log_entry)) { @@ -8266,31 +8269,41 @@ static uint32 get_next_subpartition_via_walking(PARTITION_ITERATOR *part_iter) return res; } +/* used in error messages below */ +static const char *longest_str(const char *s1, const char *s2, + const char *s3=0) +{ + if (strlen(s2) > strlen(s1)) s1= s2; + if (s3 && strlen(s3) > strlen(s1)) s1= s3; + return s1; +} + /* Create partition names SYNOPSIS create_partition_name() - out:out Created partition name string + out:out The buffer for the created partition name string + must be *at least* of FN_REFLEN+1 bytes in1 First part in2 Second part name_variant Normal, temporary or renamed partition name RETURN VALUE - NONE + 0 if ok, error if name too long DESCRIPTION This method is used to calculate the partition name, service routine to the del_ren_cre_table method. */ -void create_partition_name(char *out, const char *in1, - const char *in2, uint name_variant, - bool translate) +int create_partition_name(char *out, size_t outlen, const char *in1, + const char *in2, uint name_variant, bool translate) { char transl_part_name[FN_REFLEN]; - const char *transl_part; + const char *transl_part, *end; + DBUG_ASSERT(outlen >= FN_REFLEN + 1); // consistency! same limit everywhere if (translate) { @@ -8300,11 +8313,17 @@ void create_partition_name(char *out, const char *in1, else transl_part= in2; if (name_variant == NORMAL_PART_NAME) - strxmov(out, in1, "#P#", transl_part, NullS); + end= strxnmov(out, outlen-1, in1, "#P#", transl_part, NullS); else if (name_variant == TEMP_PART_NAME) - strxmov(out, in1, "#P#", transl_part, "#TMP#", NullS); + end= strxnmov(out, outlen-1, in1, "#P#", transl_part, "#TMP#", NullS); else if (name_variant == RENAMED_PART_NAME) - strxmov(out, in1, "#P#", transl_part, "#REN#", NullS); + end= strxnmov(out, outlen-1, in1, "#P#", transl_part, "#REN#", NullS); + if (end - out == static_cast<ptrdiff_t>(outlen-1)) + { + my_error(ER_PATH_LENGTH, MYF(0), longest_str(in1, transl_part)); + return HA_WRONG_CREATE_OPTION; + } + return 0; } @@ -8313,37 +8332,46 @@ void create_partition_name(char *out, const char *in1, SYNOPSIS create_subpartition_name() - out:out Created partition name string + out:out The buffer for the created partition name string + must be *at least* of FN_REFLEN+1 bytes in1 First part in2 Second part in3 Third part name_variant Normal, temporary or renamed partition name RETURN VALUE - NONE + 0 if ok, error if name too long DESCRIPTION This method is used to calculate the subpartition name, service routine to the del_ren_cre_table method. */ -void create_subpartition_name(char *out, const char *in1, - const char *in2, const char *in3, - uint name_variant) +int create_subpartition_name(char *out, size_t outlen, + const char *in1, const char *in2, + const char *in3, uint name_variant) { - char transl_part_name[FN_REFLEN], transl_subpart_name[FN_REFLEN]; + char transl_part_name[FN_REFLEN], transl_subpart_name[FN_REFLEN], *end; + DBUG_ASSERT(outlen >= FN_REFLEN + 1); // consistency! same limit everywhere tablename_to_filename(in2, transl_part_name, FN_REFLEN); tablename_to_filename(in3, transl_subpart_name, FN_REFLEN); if (name_variant == NORMAL_PART_NAME) - strxmov(out, in1, "#P#", transl_part_name, - "#SP#", transl_subpart_name, NullS); + end= strxnmov(out, outlen-1, in1, "#P#", transl_part_name, + "#SP#", transl_subpart_name, NullS); else if (name_variant == TEMP_PART_NAME) - strxmov(out, in1, "#P#", transl_part_name, - "#SP#", transl_subpart_name, "#TMP#", NullS); + end= strxnmov(out, outlen-1, in1, "#P#", transl_part_name, + "#SP#", transl_subpart_name, "#TMP#", NullS); else if (name_variant == RENAMED_PART_NAME) - strxmov(out, in1, "#P#", transl_part_name, - "#SP#", transl_subpart_name, "#REN#", NullS); + end= strxnmov(out, outlen-1, in1, "#P#", transl_part_name, + "#SP#", transl_subpart_name, "#REN#", NullS); + if (end - out == static_cast<ptrdiff_t>(outlen-1)) + { + my_error(ER_PATH_LENGTH, MYF(0), + longest_str(in1, transl_part_name, transl_subpart_name)); + return HA_WRONG_CREATE_OPTION; + } + return 0; } uint get_partition_field_store_length(Field *field) diff --git a/sql/sql_partition.h b/sql/sql_partition.h index b560c53562d..76f162920f1 100644 --- a/sql/sql_partition.h +++ b/sql/sql_partition.h @@ -277,12 +277,12 @@ bool partition_key_modified(TABLE *table, const MY_BITMAP *fields); #define partition_key_modified(X,Y) 0 #endif -void create_partition_name(char *out, const char *in1, - const char *in2, uint name_variant, - bool translate); -void create_subpartition_name(char *out, const char *in1, - const char *in2, const char *in3, - uint name_variant); +int __attribute__((warn_unused_result)) + create_partition_name(char *out, size_t outlen, const char *in1, const char + *in2, uint name_variant, bool translate); +int __attribute__((warn_unused_result)) + create_subpartition_name(char *out, size_t outlen, const char *in1, const + char *in2, const char *in3, uint name_variant); void set_field_ptr(Field **ptr, const uchar *new_buf, const uchar *old_buf); void set_key_field_ptr(KEY *key_info, const uchar *new_buf, diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc index 9e67a21e8f4..a9f179e3a10 100644 --- a/sql/sql_partition_admin.cc +++ b/sql/sql_partition_admin.cc @@ -492,7 +492,7 @@ bool Sql_cmd_alter_table_exchange_partition:: partition_element *part_elem; char *partition_name; char temp_name[FN_REFLEN+1]; - char part_file_name[FN_REFLEN+1]; + char part_file_name[2*FN_REFLEN+1]; char swap_file_name[FN_REFLEN+1]; char temp_file_name[FN_REFLEN+1]; uint swap_part_id; @@ -590,9 +590,9 @@ bool Sql_cmd_alter_table_exchange_partition:: temp_name, "", FN_IS_TMP); if (!(part_elem= part_table->part_info->get_part_elem(partition_name, - part_file_name + - part_file_name_len, - &swap_part_id))) + part_file_name + part_file_name_len, + sizeof(part_file_name) - part_file_name_len, + &swap_part_id))) { // my_error(ER_UNKNOWN_PARTITION, MYF(0), partition_name, // part_table->alias); diff --git a/sql/threadpool_unix.cc b/sql/threadpool_unix.cc index 2987badcb7e..5d46b8790c5 100644 --- a/sql/threadpool_unix.cc +++ b/sql/threadpool_unix.cc @@ -982,24 +982,26 @@ static void thread_group_close(thread_group_t *thread_group) if (pipe(thread_group->shutdown_pipe)) { - DBUG_VOID_RETURN; + goto end; } /* Wake listener */ if (io_poll_associate_fd(thread_group->pollfd, thread_group->shutdown_pipe[0], NULL)) { - DBUG_VOID_RETURN; + goto end; + } + { + char c= 0; + if (write(thread_group->shutdown_pipe[1], &c, 1) < 0) + goto end; } - char c= 0; - if (write(thread_group->shutdown_pipe[1], &c, 1) < 0) - DBUG_VOID_RETURN; - /* Wake all workers. */ while(wake_thread(thread_group) == 0) { } +end: mysql_mutex_unlock(&thread_group->mutex); DBUG_VOID_RETURN; diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index ca07cc80a1a..6842319b86d 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -1688,7 +1688,6 @@ int ha_archive::info(uint flag) stats.update_time= (ulong) file_stat.st_mtime; if (flag & HA_STATUS_CONST) { - stats.max_data_file_length= share->rows_recorded * stats.mean_rec_length; stats.max_data_file_length= MAX_FILE_SIZE; stats.create_time= (ulong) file_stat.st_ctime; } diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index e143ed793e4..defa11ad6b4 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -1263,6 +1263,7 @@ static my_bool translog_set_lsn_for_files(uint32 from_file, uint32 to_file, mysql_file_close(fd, MYF(MY_WME)))) { translog_stop_writing(); + mysql_mutex_unlock(&log_descriptor.file_header_lock); DBUG_RETURN(1); } } @@ -2277,10 +2278,11 @@ static void translog_set_only_in_buffers(TRANSLOG_ADDRESS in_buffers) if (cmp_translog_addr(in_buffers, log_descriptor.in_buffers_only) > 0) { if (translog_status != TRANSLOG_OK) - DBUG_VOID_RETURN; + goto end; log_descriptor.in_buffers_only= in_buffers; DBUG_PRINT("info", ("set new in_buffers_only")); } +end: mysql_mutex_unlock(&log_descriptor.sent_to_disk_lock); DBUG_VOID_RETURN; } diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c index b5fa9497065..d385104fc47 100644 --- a/storage/maria/ma_pagecache.c +++ b/storage/maria/ma_pagecache.c @@ -3484,6 +3484,7 @@ restart: lock_to_read[lock].unlock_lock, unlock_pin, FALSE)) { + pagecache_pthread_mutex_unlock(&pagecache->cache_lock); DBUG_ASSERT(0); return (uchar*) 0; } diff --git a/storage/mroonga/mrn_table.cpp b/storage/mroonga/mrn_table.cpp index a2ebbdeea95..3320fb8ff30 100644 --- a/storage/mroonga/mrn_table.cpp +++ b/storage/mroonga/mrn_table.cpp @@ -202,7 +202,7 @@ void mrn_get_partition_info(const char *table_name, uint table_name_length, const TABLE *table, partition_element **part_elem, partition_element **sub_elem) { - char tmp_name[FN_LEN]; + char tmp_name[FN_REFLEN + 1]; partition_info *part_info = table->part_info; partition_element *tmp_part_elem = NULL, *tmp_sub_elem = NULL; bool tmp_flg = FALSE, tmp_find_flg = FALSE; @@ -224,9 +224,10 @@ void mrn_get_partition_info(const char *table_name, uint table_name_length, List_iterator<partition_element> sub_it((*part_elem)->subpartitions); while ((*sub_elem = sub_it++)) { - create_subpartition_name(tmp_name, table->s->path.str, - (*part_elem)->partition_name, (*sub_elem)->partition_name, - NORMAL_PART_NAME); + if (create_subpartition_name(tmp_name, sizeof(tmp_name), table->s->path.str, + (*part_elem)->partition_name, (*sub_elem)->partition_name, + NORMAL_PART_NAME)) + DBUG_VOID_RETURN; DBUG_PRINT("info", ("mroonga tmp_name=%s", tmp_name)); if (table_name && !memcmp(table_name, tmp_name, table_name_length + 1)) DBUG_VOID_RETURN; @@ -243,8 +244,9 @@ void mrn_get_partition_info(const char *table_name, uint table_name_length, } } } else { - create_partition_name(tmp_name, table->s->path.str, - (*part_elem)->partition_name, NORMAL_PART_NAME, TRUE); + if (create_partition_name(tmp_name, sizeof(tmp_name), table->s->path.str, + (*part_elem)->partition_name, NORMAL_PART_NAME, TRUE)) + DBUG_VOID_RETURN; DBUG_PRINT("info", ("mroonga tmp_name=%s", tmp_name)); if (table_name && !memcmp(table_name, tmp_name, table_name_length + 1)) DBUG_VOID_RETURN; diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index d9dc23644d1..94d9f2257e1 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -6941,7 +6941,7 @@ void spider_get_partition_info( partition_element **part_elem, partition_element **sub_elem ) { - char tmp_name[FN_LEN]; + char tmp_name[FN_REFLEN + 1]; partition_element *tmp_part_elem = NULL, *tmp_sub_elem = NULL; bool tmp_flg = FALSE, tmp_find_flg = FALSE; DBUG_ENTER("spider_get_partition_info"); @@ -6962,9 +6962,10 @@ void spider_get_partition_info( List_iterator<partition_element> sub_it((*part_elem)->subpartitions); while ((*sub_elem = sub_it++)) { - create_subpartition_name(tmp_name, table_share->path.str, - (*part_elem)->partition_name, (*sub_elem)->partition_name, - NORMAL_PART_NAME); + if (create_subpartition_name(tmp_name, sizeof(tmp_name), + table_share->path.str, (*part_elem)->partition_name, + (*sub_elem)->partition_name, NORMAL_PART_NAME)) + DBUG_VOID_RETURN; DBUG_PRINT("info",("spider tmp_name=%s", tmp_name)); if (!memcmp(table_name, tmp_name, table_name_length + 1)) DBUG_VOID_RETURN; @@ -6980,8 +6981,10 @@ void spider_get_partition_info( } } } else { - create_partition_name(tmp_name, table_share->path.str, - (*part_elem)->partition_name, NORMAL_PART_NAME, TRUE); + if (create_partition_name(tmp_name, sizeof(tmp_name), + table_share->path.str, (*part_elem)->partition_name, + NORMAL_PART_NAME, TRUE)) + DBUG_VOID_RETURN; DBUG_PRINT("info",("spider tmp_name=%s", tmp_name)); if (!memcmp(table_name, tmp_name, table_name_length + 1)) DBUG_VOID_RETURN; @@ -8447,7 +8450,7 @@ int spider_discover_table_structure( spider_free_share_resource_only(spider_share); #ifdef WITH_PARTITION_STORAGE_ENGINE } else { - char tmp_name[FN_LEN]; + char tmp_name[FN_REFLEN + 1]; List_iterator<partition_element> part_it(part_info->partitions); partition_element *part_elem, *sub_elem; while ((part_elem = part_it++)) @@ -8458,9 +8461,10 @@ int spider_discover_table_structure( while ((sub_elem = sub_it++)) { str.length(str_len); - create_subpartition_name(tmp_name, table_name, - (part_elem)->partition_name, (sub_elem)->partition_name, - NORMAL_PART_NAME); + if (create_subpartition_name(tmp_name, sizeof(tmp_name), table_name, + (part_elem)->partition_name, (sub_elem)->partition_name, + NORMAL_PART_NAME)) + DBUG_RETURN(1); DBUG_PRINT("info",("spider tmp_name=%s", tmp_name)); if (!(spider_share = spider_create_share(table_name, share, part_info, @@ -8483,8 +8487,9 @@ int spider_discover_table_structure( break; } else { str.length(str_len); - create_partition_name(tmp_name, table_name, - (part_elem)->partition_name, NORMAL_PART_NAME, TRUE); + if (create_partition_name(tmp_name, sizeof(tmp_name), table_name, + (part_elem)->partition_name, NORMAL_PART_NAME, TRUE)) + DBUG_RETURN(1); DBUG_PRINT("info",("spider tmp_name=%s", tmp_name)); if (!(spider_share = spider_create_share(table_name, share, part_info, |