diff options
author | unknown <tsmith@quadxeon.mysql.com> | 2007-05-01 12:40:43 +0200 |
---|---|---|
committer | unknown <tsmith@quadxeon.mysql.com> | 2007-05-01 12:40:43 +0200 |
commit | f827425712cb7cf2afdb729365615554582411c2 (patch) | |
tree | 1a4db62bffc95d247ed51f9f518a80d921a8bf48 | |
parent | ad42991306a14ec10170652e82c252de023b523c (diff) | |
parent | 0fc282bbe190cce5a32754f606456fe363a6b194 (diff) | |
download | mariadb-git-f827425712cb7cf2afdb729365615554582411c2.tar.gz |
Merge quadxeon.mysql.com:/benchmarks/ext3/TOSAVE/tsmith/bk/50
into quadxeon.mysql.com:/benchmarks/ext3/TOSAVE/tsmith/bk/maint/50
mysql-test/r/alter_table.result:
Auto merged
mysql-test/t/alter_table.test:
Auto merged
29 files changed, 650 insertions, 277 deletions
diff --git a/client/mysqldump.c b/client/mysqldump.c index 63db2cc268e..4f908b531b1 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1489,8 +1489,15 @@ static uint dump_routines_for_db(char *db) routine body of other routines that are not the creator of! */ DBUG_PRINT("info",("length of body for %s row[2] '%s' is %d", - routine_name, row[2], (int) strlen(row[2]))); - if (strlen(row[2])) + routine_name, row[2] ? row[2] : "(null)", + row[2] ? (int) strlen(row[2]) : 0)); + if (row[2] == NULL) + { + fprintf(sql_file, "\n-- insufficient privileges to %s\n", query_buff); + fprintf(sql_file, "-- does %s have permissions on mysql.proc?\n\n", current_user); + maybe_die(EX_MYSQLERR,"%s has insufficent privileges to %s!", current_user, query_buff); + } + else if (strlen(row[2])) { char *query_str= NULL; char *definer_begin; @@ -1540,7 +1547,7 @@ static uint dump_routines_for_db(char *db) /* we need to change sql_mode only for the CREATE PROCEDURE/FUNCTION otherwise we may need to re-quote routine_name - */; + */ fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\"*/;;\n", row[1] /* sql_mode */); fprintf(sql_file, "/*!50003 %s */;;\n", diff --git a/extra/my_print_defaults.c b/extra/my_print_defaults.c index eb077f91ece..f5f7e68c9e6 100644 --- a/extra/my_print_defaults.c +++ b/extra/my_print_defaults.c @@ -33,7 +33,20 @@ const char *default_dbug_option="d:t:o,/tmp/my_print_defaults.trace"; static struct my_option my_long_options[] = { - {"config-file", 'c', "The config file to be used.", + /* + NB: --config-file is troublesome, because get_defaults_options() doesn't + know about it, but we pretend --config-file is like --defaults-file. In + fact they behave differently: see the comments at the top of + mysys/default.c for how --defaults-file should behave. + + This --config-file option behaves as: + - If it has a directory name part (absolute or relative), then only this + file is read; no error is given if the file doesn't exist + - If the file has no directory name part, the standard locations are + searched for a file of this name (and standard filename extensions are + added if the file has no extension) + */ + {"config-file", 'c', "Deprecated, please use --defaults-file instead. Name of config file to read; if no extension is given, default extension (e.g., .ini or .cnf) will be added", (gptr*) &config_file, (gptr*) &config_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef DBUG_OFF @@ -43,11 +56,11 @@ static struct my_option my_long_options[] = {"debug", '#', "Output debug log", (gptr*) &default_dbug_option, (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"defaults-file", 'c', "Synonym for --config-file.", + {"defaults-file", 'c', "Like --config-file, except: if first option, then read this file only, do not read global or per-user config files; should be the first option", (gptr*) &config_file, (gptr*) &config_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"defaults-extra-file", 'e', - "Read this file after the global /etc config file and before the config file in the users home directory.", + "Read this file after the global config file and before the config file in the users home directory; should be the first option", (gptr*) &my_defaults_extra_file, (gptr*) &my_defaults_extra_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"defaults-group-suffix", 'g', @@ -55,7 +68,7 @@ static struct my_option my_long_options[] = (gptr*) &my_defaults_group_suffix, (gptr*) &my_defaults_group_suffix, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"extra-file", 'e', - "Synonym for --defaults-extra-file.", + "Deprecated. Synonym for --defaults-extra-file.", (gptr*) &my_defaults_extra_file, (gptr*) &my_defaults_extra_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -86,7 +99,7 @@ static void usage(my_bool version) my_print_help(my_long_options); my_print_default_files(config_file); my_print_variables(my_long_options); - printf("\nExample usage:\n%s --config-file=my client mysql\n", my_progname); + printf("\nExample usage:\n%s --defaults-file=example.cnf client mysql\n", my_progname); } #include <help_end.h> diff --git a/include/my_global.h b/include/my_global.h index f446c283d50..e9b371d8d30 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -784,13 +784,20 @@ typedef SOCKET_SIZE_TYPE size_socket; #define SSIZE_MAX ((~((size_t) 0)) / 2) #endif +#ifndef HAVE_FINITE +#define finite(x) (1.0 / fabs(x) > 0.0) +#endif + +#ifndef HAVE_ISNAN +#define isnan(x) ((x) != (x)) +#endif + #if !defined(HAVE_ISINF) /* The configure check for "isinf with math.h" has failed */ #ifdef isinf #undef isinf #endif -/* Define isinf to never say that X is infinite */ -#define isinf(X) 0 +#define isinf(X) (!finite(X) && !isnan(X)) #endif /* Define missing math constants. */ diff --git a/mysql-test/include/have_lowercase1.inc b/mysql-test/include/have_lowercase1.inc new file mode 100644 index 00000000000..1b33432dbe3 --- /dev/null +++ b/mysql-test/include/have_lowercase1.inc @@ -0,0 +1,4 @@ +--require r/lowercase1.require +--disable_query_log +show variables like 'lower_case_table_names'; +--enable_query_log diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl index a2f22ef8870..d08208d37a6 100644 --- a/mysql-test/lib/mtr_report.pl +++ b/mysql-test/lib/mtr_report.pl @@ -238,7 +238,7 @@ sub mtr_report_stats ($) { } if (!$::opt_extern) { - print "The servers where restarted $tot_restarts times\n"; + print "The servers were restarted $tot_restarts times\n"; } if ( $::opt_timer ) @@ -357,7 +357,7 @@ sub mtr_report_stats ($) { if ( $tot_failed != 0 || $found_problems) { - mtr_error("there where failing test cases"); + mtr_error("there were failing test cases"); } } diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 82c35ff963a..280cedb8b89 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -860,3 +860,27 @@ ALTER TABLE t1 ADD d INT; ALTER TABLE t1 ADD KEY (d(20)); ERROR HY000: Incorrect sub part key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique sub keys DROP TABLE t1; +create table t1(id int(8) primary key auto_increment) engine=heap; +insert into t1 values (null); +insert into t1 values (null); +select * from t1; +id +1 +2 +alter table t1 auto_increment = 50; +alter table t1 engine = myisam; +insert into t1 values (null); +select * from t1; +id +1 +2 +50 +alter table t1 engine = heap; +insert into t1 values (null); +select * from t1; +id +1 +2 +50 +51 +drop table t1; diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result index fc9bfb3b612..ace94217fdc 100644 --- a/mysql-test/r/func_math.result +++ b/mysql-test/r/func_math.result @@ -143,9 +143,6 @@ select format(col2,6) from t1 where col1=7; format(col2,6) 1,234,567,890,123,456.123450 drop table t1; -select round(150, 2); -round(150, 2) -150.00 select ceil(0.09); ceil(0.09) 1 @@ -156,11 +153,11 @@ create table t1 select round(1, 6); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `round(1, 6)` decimal(7,6) NOT NULL default '0.000000' + `round(1, 6)` int(1) NOT NULL default '0' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 select * from t1; round(1, 6) -1.000000 +1 drop table t1; select abs(-2) * -2; abs(-2) * -2 @@ -238,3 +235,91 @@ format(t2.f2-t2.f1+1,0) 10,000 drop table t1, t2; set names default; +select cast(-2 as unsigned), 18446744073709551614, -2; +cast(-2 as unsigned) 18446744073709551614 -2 +18446744073709551614 18446744073709551614 -2 +select abs(cast(-2 as unsigned)), abs(18446744073709551614), abs(-2); +abs(cast(-2 as unsigned)) abs(18446744073709551614) abs(-2) +18446744073709551614 18446744073709551614 2 +select ceiling(cast(-2 as unsigned)), ceiling(18446744073709551614), ceiling(-2); +ceiling(cast(-2 as unsigned)) ceiling(18446744073709551614) ceiling(-2) +18446744073709551614 18446744073709551614 -2 +select floor(cast(-2 as unsigned)), floor(18446744073709551614), floor(-2); +floor(cast(-2 as unsigned)) floor(18446744073709551614) floor(-2) +18446744073709551614 18446744073709551614 -2 +select format(cast(-2 as unsigned), 2), format(18446744073709551614, 2), format(-2, 2); +format(cast(-2 as unsigned), 2) format(18446744073709551614, 2) format(-2, 2) +18,446,744,073,709,551,614.00 18,446,744,073,709,551,614.00 -2.00 +select sqrt(cast(-2 as unsigned)), sqrt(18446744073709551614), sqrt(-2); +sqrt(cast(-2 as unsigned)) sqrt(18446744073709551614) sqrt(-2) +4294967296 4294967296 NULL +select round(cast(-2 as unsigned), 1), round(18446744073709551614, 1), round(-2, 1); +round(cast(-2 as unsigned), 1) round(18446744073709551614, 1) round(-2, 1) +18446744073709551614 18446744073709551614 -2 +select round(4, cast(-2 as unsigned)), round(4, 18446744073709551614), round(4, -2); +round(4, cast(-2 as unsigned)) round(4, 18446744073709551614) round(4, -2) +4 4 0 +select truncate(cast(-2 as unsigned), 1), truncate(18446744073709551614, 1), truncate(-2, 1); +truncate(cast(-2 as unsigned), 1) truncate(18446744073709551614, 1) truncate(-2, 1) +18446744073709551614 18446744073709551614 -2 +select truncate(4, cast(-2 as unsigned)), truncate(4, 18446744073709551614), truncate(4, -2); +truncate(4, cast(-2 as unsigned)) truncate(4, 18446744073709551614) truncate(4, -2) +4 4 0 +select round(10000000000000000000, -19), truncate(10000000000000000000, -19); +round(10000000000000000000, -19) truncate(10000000000000000000, -19) +10000000000000000000 10000000000000000000 +select round(1e0, -309), truncate(1e0, -309); +round(1e0, -309) truncate(1e0, -309) +0 0 +select round(1e1,308), truncate(1e1, 308); +round(1e1,308) truncate(1e1, 308) +10 10 +select round(1e1, 2147483648), truncate(1e1, 2147483648); +round(1e1, 2147483648) truncate(1e1, 2147483648) +10 10 +select round(1.1e1, 4294967295), truncate(1.1e1, 4294967295); +round(1.1e1, 4294967295) truncate(1.1e1, 4294967295) +11 11 +select round(1.12e1, 4294967296), truncate(1.12e1, 4294967296); +round(1.12e1, 4294967296) truncate(1.12e1, 4294967296) +11.2 11.2 +select round(1.5, 2147483640), truncate(1.5, 2147483640); +round(1.5, 2147483640) truncate(1.5, 2147483640) +1.500000000000000000000000000000 1.500000000000000000000000000000 +select round(1.5, -2147483649), round(1.5, 2147483648); +round(1.5, -2147483649) round(1.5, 2147483648) +0 1.500000000000000000000000000000 +select truncate(1.5, -2147483649), truncate(1.5, 2147483648); +truncate(1.5, -2147483649) truncate(1.5, 2147483648) +0 1.500000000000000000000000000000 +select round(1.5, -4294967296), round(1.5, 4294967296); +round(1.5, -4294967296) round(1.5, 4294967296) +0 1.500000000000000000000000000000 +select truncate(1.5, -4294967296), truncate(1.5, 4294967296); +truncate(1.5, -4294967296) truncate(1.5, 4294967296) +0 1.500000000000000000000000000000 +select round(1.5, -9223372036854775808), round(1.5, 9223372036854775808); +round(1.5, -9223372036854775808) round(1.5, 9223372036854775808) +0 1.500000000000000000000000000000 +select truncate(1.5, -9223372036854775808), truncate(1.5, 9223372036854775808); +truncate(1.5, -9223372036854775808) truncate(1.5, 9223372036854775808) +0 1.500000000000000000000000000000 +select round(1.5, 18446744073709551615), truncate(1.5, 18446744073709551615); +round(1.5, 18446744073709551615) truncate(1.5, 18446744073709551615) +1.500000000000000000000000000000 1.500000000000000000000000000000 +select round(18446744073709551614, -1), truncate(18446744073709551614, -1); +round(18446744073709551614, -1) truncate(18446744073709551614, -1) +18446744073709551610 18446744073709551610 +select round(4, -4294967200), truncate(4, -4294967200); +round(4, -4294967200) truncate(4, -4294967200) +0 0 +select mod(cast(-2 as unsigned), 3), mod(18446744073709551614, 3), mod(-2, 3); +mod(cast(-2 as unsigned), 3) mod(18446744073709551614, 3) mod(-2, 3) +2 2 -2 +select mod(5, cast(-2 as unsigned)), mod(5, 18446744073709551614), mod(5, -2); +mod(5, cast(-2 as unsigned)) mod(5, 18446744073709551614) mod(5, -2) +5 5 1 +select pow(cast(-2 as unsigned), 5), pow(18446744073709551614, 5), pow(-2, 5); +pow(cast(-2 as unsigned), 5) pow(18446744073709551614, 5) pow(-2, 5) +2.1359870359209e+96 2.1359870359209e+96 -32 +End of 5.0 tests diff --git a/mysql-test/r/lowercase1.require b/mysql-test/r/lowercase1.require new file mode 100644 index 00000000000..0341f838f7b --- /dev/null +++ b/mysql-test/r/lowercase1.require @@ -0,0 +1,2 @@ +Variable_name Value +lower_case_table_names 1 diff --git a/mysql-test/r/lowercase_mixed_tmpdir.result b/mysql-test/r/lowercase_mixed_tmpdir.result new file mode 100644 index 00000000000..e11b5e4c286 --- /dev/null +++ b/mysql-test/r/lowercase_mixed_tmpdir.result @@ -0,0 +1,6 @@ +drop table if exists t1; +create table t1 (id int) engine=myisam; +insert into t1 values (1); +create temporary table t2 select * from t1; +drop temporary table t2; +drop table t1; diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 5caaa9264d0..d9198ffeb48 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -3282,6 +3282,33 @@ v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VI drop database bug23491_original; drop database bug23491_restore; use test; +# +# Bug 27293: mysqldump crashes when dumping routines +# defined by a different user +# +# Bug #22761: mysqldump reports no errors when using +# --routines without mysql.proc privileges +# +create database mysqldump_test_db; +grant all privileges on mysqldump_test_db.* to user1; +grant all privileges on mysqldump_test_db.* to user2; +create procedure mysqldump_test_db.sp1() select 'hello'; +DELIMITER ;; + +-- insufficient privileges to SHOW CREATE PROCEDURE `sp1` +-- does user2 have permissions on mysql.proc? + +DELIMITER ; +DELIMITER ;; +/*!50003 SET SESSION SQL_MODE=""*/;; +/*!50003 CREATE*/ /*!50020 DEFINER=`user1`@`%`*/ /*!50003 PROCEDURE `sp1`() +select 'hello' */;; +/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;; +DELIMITER ; +drop procedure sp1; +drop user user1; +drop user user2; +drop database mysqldump_test_db; # # End of 5.0 tests # diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 359a929d9a3..c103de81bd7 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -763,7 +763,7 @@ truncate(99999999999999999999999999999999999999,31) 99999999999999999999999999999999999999.000000000000000000000000000000 select truncate(99.999999999999999999999999999999999999,31); truncate(99.999999999999999999999999999999999999,31) -100.000000000000000000000000000000 +99.999999999999999999999999999999 select truncate(99999999999999999999999999999999999999,-31); truncate(99999999999999999999999999999999999999,-31) 99999990000000000000000000000000000000 diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index 748c2644eb9..dc7c7642a9b 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -457,3 +457,38 @@ a quux 2 0.100000000000000000000000000000 3 NULL DROP TABLE t1; +set tmp_table_size=1024; +create table t1 (id int, a int, key idx(a)); +create table t2 (id int unsigned not null auto_increment primary key, a int); +insert into t2(a) values(1),(2),(3),(4),(5),(6),(7),(8); +insert into t2(a) select a from t2; +insert into t2(a) select a from t2; +insert into t2(a) select a from t2; +update t2 set a=id; +insert into t1 select * from t2; +select count(*) from t1 join t2 on (t1.a=t2.a); +count(*) +64 +update t1 join t2 on (t1.a=t2.a) set t1.id=t2.id; +affected rows: 0 +info: Rows matched: 64 Changed: 0 Warnings: 0 +insert into t2(a) select a from t2; +update t2 set a=id; +truncate t1; +insert into t1 select * from t2; +select count(*) from t1 join t2 on (t1.a=t2.a); +count(*) +128 +update t1 join t2 on (t1.a=t2.a) set t1.id=t2.id; +affected rows: 0 +info: Rows matched: 128 Changed: 0 Warnings: 0 +update t1 set a=1; +update t2 set a=1; +select count(*) from t1 join t2 on (t1.a=t2.a); +count(*) +16384 +update t1 join t2 on (t1.a=t2.a) set t1.id=t2.id; +affected rows: 127 +info: Rows matched: 128 Changed: 127 Warnings: 0 +drop table t1,t2; +End of 5.0 tests diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 307138added..83686f31e9e 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -636,3 +636,29 @@ ALTER TABLE t1 ADD d INT; ALTER TABLE t1 ADD KEY (d(20)); DROP TABLE t1; +# Bug#25262 Auto Increment lost when changing Engine type +# + +create table t1(id int(8) primary key auto_increment) engine=heap; + +insert into t1 values (null); +insert into t1 values (null); + +select * from t1; + +# Set auto increment to 50 +alter table t1 auto_increment = 50; + +# Alter to myisam +alter table t1 engine = myisam; + +# This insert should get id 50 +insert into t1 values (null); +select * from t1; + +# Alter to heap again +alter table t1 engine = heap; +insert into t1 values (null); +select * from t1; + +drop table t1; diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test index 4041c267134..2ba07dfc581 100644 --- a/mysql-test/t/func_math.test +++ b/mysql-test/t/func_math.test @@ -83,11 +83,6 @@ drop table t1; # -# Bug #10083 (round doesn't increase decimals) -# -select round(150, 2); - -# # Bug @10632 (Ceiling function returns wrong answer) # select ceil(0.09); @@ -177,3 +172,37 @@ select format(t2.f2-t2.f1+1,0) from t1,t2 where t1.f2 = t2.f3 order by t1.f1; drop table t1, t2; set names default; + +# Bug 24912 -- misc functions have trouble with unsigned + +select cast(-2 as unsigned), 18446744073709551614, -2; +select abs(cast(-2 as unsigned)), abs(18446744073709551614), abs(-2); +select ceiling(cast(-2 as unsigned)), ceiling(18446744073709551614), ceiling(-2); +select floor(cast(-2 as unsigned)), floor(18446744073709551614), floor(-2); +select format(cast(-2 as unsigned), 2), format(18446744073709551614, 2), format(-2, 2); +select sqrt(cast(-2 as unsigned)), sqrt(18446744073709551614), sqrt(-2); +select round(cast(-2 as unsigned), 1), round(18446744073709551614, 1), round(-2, 1); +select round(4, cast(-2 as unsigned)), round(4, 18446744073709551614), round(4, -2); +select truncate(cast(-2 as unsigned), 1), truncate(18446744073709551614, 1), truncate(-2, 1); +select truncate(4, cast(-2 as unsigned)), truncate(4, 18446744073709551614), truncate(4, -2); +select round(10000000000000000000, -19), truncate(10000000000000000000, -19); +select round(1e0, -309), truncate(1e0, -309); +select round(1e1,308), truncate(1e1, 308); +select round(1e1, 2147483648), truncate(1e1, 2147483648); +select round(1.1e1, 4294967295), truncate(1.1e1, 4294967295); +select round(1.12e1, 4294967296), truncate(1.12e1, 4294967296); +select round(1.5, 2147483640), truncate(1.5, 2147483640); +select round(1.5, -2147483649), round(1.5, 2147483648); +select truncate(1.5, -2147483649), truncate(1.5, 2147483648); +select round(1.5, -4294967296), round(1.5, 4294967296); +select truncate(1.5, -4294967296), truncate(1.5, 4294967296); +select round(1.5, -9223372036854775808), round(1.5, 9223372036854775808); +select truncate(1.5, -9223372036854775808), truncate(1.5, 9223372036854775808); +select round(1.5, 18446744073709551615), truncate(1.5, 18446744073709551615); +select round(18446744073709551614, -1), truncate(18446744073709551614, -1); +select round(4, -4294967200), truncate(4, -4294967200); +select mod(cast(-2 as unsigned), 3), mod(18446744073709551614, 3), mod(-2, 3); +select mod(5, cast(-2 as unsigned)), mod(5, 18446744073709551614), mod(5, -2); +select pow(cast(-2 as unsigned), 5), pow(18446744073709551614, 5), pow(-2, 5); + +--echo End of 5.0 tests diff --git a/mysql-test/t/lowercase_mixed_tmpdir-master.opt b/mysql-test/t/lowercase_mixed_tmpdir-master.opt new file mode 100644 index 00000000000..3d21ea72f6b --- /dev/null +++ b/mysql-test/t/lowercase_mixed_tmpdir-master.opt @@ -0,0 +1,2 @@ +--lower-case-table-names=1 +--tmpdir=$MYSQLTEST_VARDIR/tmp/MixedCase diff --git a/mysql-test/t/lowercase_mixed_tmpdir-master.sh b/mysql-test/t/lowercase_mixed_tmpdir-master.sh new file mode 100644 index 00000000000..95c26e3aa02 --- /dev/null +++ b/mysql-test/t/lowercase_mixed_tmpdir-master.sh @@ -0,0 +1,6 @@ +# This test requires a non-lowercase tmpdir directory on a case-sensitive +# filesystem. + +d="$MYSQLTEST_VARDIR/tmp/MixedCase" +test -d "$d" || mkdir "$d" +rm -f "$d"/* diff --git a/mysql-test/t/lowercase_mixed_tmpdir.test b/mysql-test/t/lowercase_mixed_tmpdir.test new file mode 100644 index 00000000000..6bd3a6f2acc --- /dev/null +++ b/mysql-test/t/lowercase_mixed_tmpdir.test @@ -0,0 +1,12 @@ +--source include/have_case_sensitive_file_system.inc +--source include/have_lowercase1.inc + +--disable_warnings +drop table if exists t1; +--enable_warnings + +create table t1 (id int) engine=myisam; +insert into t1 values (1); +create temporary table t2 select * from t1; +drop temporary table t2; +drop table t1; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 126412057ab..4c4690520c6 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -1495,6 +1495,41 @@ drop database bug23491_original; drop database bug23491_restore; use test; + + +--echo # +--echo # Bug 27293: mysqldump crashes when dumping routines +--echo # defined by a different user +--echo # +--echo # Bug #22761: mysqldump reports no errors when using +--echo # --routines without mysql.proc privileges +--echo # + +create database mysqldump_test_db; + +grant all privileges on mysqldump_test_db.* to user1; +grant all privileges on mysqldump_test_db.* to user2; + +connect (user27293,localhost,user1,,mysqldump_test_db,$MASTER_MYPORT,$MASTER_MYSOCK); +connection user27293; + +create procedure mysqldump_test_db.sp1() select 'hello'; + +--error 2 +--exec $MYSQL_DUMP -f --compact --user=user2 --password= -h 127.0.0.1 -P $MASTER_MYPORT --routines mysqldump_test_db + +--exec $MYSQL_DUMP -f --compact --user=user1 --password= -h 127.0.0.1 -P $MASTER_MYPORT --routines mysqldump_test_db + +drop procedure sp1; + +connection default; +drop user user1; +drop user user2; + +drop database mysqldump_test_db; + + + --echo # --echo # End of 5.0 tests --echo # diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test index 6cec940d286..f79c9e773aa 100644 --- a/mysql-test/t/update.test +++ b/mysql-test/t/update.test @@ -376,3 +376,58 @@ INSERT INTO t1( a ) SELECT * FROM t1; DROP TABLE t1; + +# +# Bug #22364: Inconsistent "matched rows" when executing UPDATE +# + +connect (con1,localhost,root,,test); +connection con1; + +set tmp_table_size=1024; + +# Create the test tables +create table t1 (id int, a int, key idx(a)); +create table t2 (id int unsigned not null auto_increment primary key, a int); +insert into t2(a) values(1),(2),(3),(4),(5),(6),(7),(8); +insert into t2(a) select a from t2; +insert into t2(a) select a from t2; +insert into t2(a) select a from t2; +update t2 set a=id; +insert into t1 select * from t2; + +# Check that the number of matched rows is correct when the temporary +# table is small enough to not be converted to MyISAM +select count(*) from t1 join t2 on (t1.a=t2.a); +--enable_info +update t1 join t2 on (t1.a=t2.a) set t1.id=t2.id; +--disable_info + +# Increase table sizes +insert into t2(a) select a from t2; +update t2 set a=id; +truncate t1; +insert into t1 select * from t2; + +# Check that the number of matched rows is correct when the temporary +# table has to be converted to MyISAM +select count(*) from t1 join t2 on (t1.a=t2.a); +--enable_info +update t1 join t2 on (t1.a=t2.a) set t1.id=t2.id; +--disable_info + +# Check that the number of matched rows is correct when there are duplicate +# key errors +update t1 set a=1; +update t2 set a=1; +select count(*) from t1 join t2 on (t1.a=t2.a); +--enable_info +update t1 join t2 on (t1.a=t2.a) set t1.id=t2.id; +--disable_info + +drop table t1,t2; + +connection default; +disconnect con1; + +--echo End of 5.0 tests diff --git a/mysys/default.c b/mysys/default.c index dc1c5a698b8..aff38b6af0b 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -877,8 +877,8 @@ void my_print_default_files(const char *conf_file) fputs(name,stdout); } } - puts(""); } + puts(""); } void print_defaults(const char *conf_file, const char **groups) diff --git a/mysys/my_copy.c b/mysys/my_copy.c index 6143700befc..ec642b4083c 100644 --- a/mysys/my_copy.c +++ b/mysys/my_copy.c @@ -111,6 +111,11 @@ int my_copy(const char *from, const char *to, myf MyFlags) err: if (from_file >= 0) VOID(my_close(from_file,MyFlags)); - if (to_file >= 0) VOID(my_close(to_file,MyFlags)); + if (to_file >= 0) + { + VOID(my_close(to_file, MyFlags)); + /* attempt to delete the to-file we've partially written */ + VOID(my_delete(to, MyFlags)); + } DBUG_RETURN(-1); } /* my_copy */ diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 63995eb1575..934d245db15 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -79,7 +79,10 @@ parse_arguments() { then # This sed command makes sure that any special chars are quoted, # so the arg gets passed exactly to the server. - args="$args "`echo "$arg" | sed -e 's,\([^a-zA-Z0-9_.-]\),\\\\\1,g'` + # XXX: This is broken; true fix requires using eval and proper + # quoting of every single arg ($basedir, $ldata, etc.) + #args="$args "`echo "$arg" | sed -e 's,\([^a-zA-Z0-9_.-]\),\\\\\1,g'` + args="$args $arg" fi ;; esac @@ -151,6 +154,7 @@ else if test -f $i/$fill_help_tables then pkgdatadir=$i + break fi done diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index a664bcfd3ad..92cfbe3ef22 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -4,9 +4,10 @@ use Getopt::Long; use POSIX qw(strftime); $|=1; -$VER="2.15"; +$VER="2.16"; + +my @defaults_options; # Leading --no-defaults, --defaults-file, etc. -$opt_config_file = undef(); $opt_example = 0; $opt_help = 0; $opt_log = undef(); @@ -49,54 +50,52 @@ sub main print "MySQL distribution.\n"; $my_print_defaults_exists= 0; } - if ($my_print_defaults_exists) + + # Remove leading defaults options from @ARGV + while (@ARGV > 0) + { + last unless $ARGV[0] =~ + /^--(?:no-defaults$|(?:defaults-file|defaults-extra-file)=)/; + push @defaults_options, (shift @ARGV); + } + + # Handle deprecated --config-file option: convert to --defaults-extra-file + foreach my $arg (@ARGV) { - foreach my $arg (@ARGV) + if ($arg =~ m/^--config-file=(.*)/) { - if ($arg =~ m/^--config-file=(.*)/) - { - if (!length($1)) - { - die "Option config-file requires an argument\n"; - } - elsif (!( -e $1 && -r $1)) - { - die "Option file '$1' doesn't exists, or is not readable\n"; - } - else - { - $opt_config_file= $1; - if (!($opt_config_file =~ m/\//)) - { - # No path. Use current working directory - $opt_config_file= "./" . $opt_config_file; - } - } - } + # Put it at the beginning of the list, so it has lower precedence + # than a correct --defaults-extra-file option + + unshift @defaults_options, "--defaults-extra-file=$1"; } - my $com= "my_print_defaults "; - $com.= "--config-file=$opt_config_file " if (defined($opt_config_file)); - $com.= "mysqld_multi"; - my @defops = `$com`; - chop @defops; - splice @ARGV, 0, 0, @defops; } - if (!GetOptions("help","example","version","mysqld=s","mysqladmin=s", - "config-file=s","user=s","password=s","log=s","no-log", - "tcp-ip", "silent","verbose")) + + foreach (@defaults_options) { - $flag_exit= 1; + $_ = quote_shell_word($_); } - if (defined($opt_config_file) && !($opt_config_file =~ m/\//)) + + # Add [mysqld_multi] options to front of @ARGV, ready for GetOptions() + unshift @ARGV, defaults_for_group('mysqld_multi'); + + # The --config-file option can be ignored; if passed on the command + # line, it's already handled; if specified in the configuration file, + # it's redundant and not useful + @ARGV= grep { not /^--config-file=/ } @ARGV; + + # We've already handled --no-defaults, --defaults-file, etc. + if (!GetOptions("help", "example", "version", "mysqld=s", "mysqladmin=s", + "user=s", "password=s", "log=s", "no-log", + "tcp-ip", "silent", "verbose")) { - # No path. Use current working directory - $opt_config_file= "./" . $opt_config_file; + $flag_exit= 1; } usage() if ($opt_help); if ($opt_verbose && $opt_silent) { - print "Both --verbose and --silent has been given. Some of the warnings "; + print "Both --verbose and --silent have been given. Some of the warnings "; print "will be disabled\nand some will be enabled.\n\n"; } @@ -168,51 +167,42 @@ sub main } } -#### -#### Quote option argument. Add double quotes around the argument -#### and escape the following: $, \, " -#### This function is needed, because my_print_defaults drops possible -#### quotes, single or double, from in front of an argument and from -#### the end. -#### +# +# Quote word for shell +# -sub quote_opt_arg +sub quote_shell_word { my ($option)= @_; - if ($option =~ m/(\-\-[a-zA-Z0-9\_\-]+)=(.*)/) - { - $option= $1; - $arg= $2; - $arg=~ s/\\/\\\\/g; # Escape escape character first to avoid doubling. - $arg=~ s/\$/\\\$/g; - $arg=~ s/\"/\\\"/g; - $arg= "\"" . $arg . "\""; - $option= $option . "=" . $arg; - } + $option =~ s!([^\w=./-])!\\$1!g; return $option; } +sub defaults_for_group +{ + my ($group) = @_; + + return () unless $my_print_defaults_exists; + + my $com= join ' ', 'my_print_defaults', @defaults_options, $group; + my @defaults = `$com`; + chomp @defaults; + return @defaults; +} + #### #### Init log file. Check for appropriate place for log file, in the following -#### order my_print_defaults mysqld datadir, @datadir@, /var/log, /tmp +#### order: my_print_defaults mysqld datadir, @datadir@ #### sub init_log { - if ($my_print_defaults_exists) + foreach my $opt (defaults_for_group('mysqld')) { - @mysqld_opts= `my_print_defaults mysqld`; - chomp @mysqld_opts; - foreach my $opt (@mysqld_opts) + if ($opt =~ m/^--datadir=(.*)/ && -d "$1" && -w "$1") { - if ($opt =~ m/^\-\-datadir[=](.*)/) - { - if (-d "$1" && -w "$1") - { - $logdir= $1; - } - } + $logdir= $1; } } if (!defined($logdir)) @@ -303,11 +293,7 @@ sub start_mysqlds() @groups = &find_groups($groupids); for ($i = 0; defined($groups[$i]); $i++) { - $com = "my_print_defaults"; - $com.= defined($opt_config_file) ? " --config-file=$opt_config_file" : ""; - $com.= " $groups[$i]"; - @options = `$com`; - chop @options; + @options = defaults_for_group($groups[$i]); $mysqld_found= 1; # The default $mysqld_found= 0 if (!length($mysqld)); @@ -326,7 +312,7 @@ sub start_mysqlds() } else { - $options[$j]= quote_opt_arg($options[$j]); + $options[$j]= quote_shell_word($options[$j]); $tmp.= " $options[$j]"; } } @@ -401,11 +387,7 @@ sub get_mysqladmin_options my ($i, @groups)= @_; my ($mysqladmin_found, $com, $tmp, $j); - $com = "my_print_defaults"; - $com.= defined($opt_config_file) ? " --config-file=$opt_config_file" : ""; - $com.= " $groups[$i]"; - @options = `$com`; - chop @options; + @options = defaults_for_group($groups[$i]); $mysqladmin_found= 1; # The default $mysqladmin_found= 0 if (!length($mysqladmin)); @@ -445,129 +427,81 @@ sub get_mysqladmin_options return $com; } -#### -#### Find groups. Takes the valid group numbers as an argument, parses -#### them, puts them in the ascending order, removes duplicates and -#### returns the wanted groups accordingly. -#### +# Return a list of option files which can be opened. Similar, but not +# identical, to behavior of my_search_option_files() +sub list_defaults_files +{ + my %opt; + foreach (@defaults_options) + { + return () if /^--no-defaults$/; + $opt{$1} = $2 if /^--defaults-(extra-file|file)=(.*)$/; + } + + return ($opt{file}) if exists $opt{file}; + + my %seen; # Don't list the same file more than once + return grep { defined $_ and not $seen{$_}++ and -f $_ and -r $_ } + ('/etc/my.cnf', + '/etc/mysql/my.cnf', + '@sysconfdir@/my.cnf', + ($ENV{MYSQL_HOME} ? "$ENV{MYSQL_HOME}/my.cnf" : undef), + $opt{'extra-file'}, + ($ENV{HOME} ? "$ENV{HOME}/.my.cnf" : undef)); +} + +# Takes a specification of GNRs (see --help), and returns a list of matching +# groups which actually are mentioned in a relevant config file sub find_groups { my ($raw_gids) = @_; - my (@groups, @data, @tmp, $line, $i, $k, @pre_gids, @gids, @tmp2, - $prev_value); - # Read the lines from the config file to variable 'data' - if (defined($opt_config_file)) - { - open(MY_CNF, "<$opt_config_file") && (@data=<MY_CNF>) && close(MY_CNF); - } - else - { - if (-f "@sysconfdir@/my.cnf" && -r "@sysconfdir@/my.cnf") - { - open(MY_CNF, "<@sysconfdir@/my.cnf") && (@tmp=<MY_CNF>) && close(MY_CNF); - } elsif (-f "/etc/my.cnf" && -r "/etc/my.cnf") - { - open(MY_CNF, "</etc/my.cnf") && (@tmp=<MY_CNF>) && close(MY_CNF); - } - for ($i = 0; ($line = shift @tmp); $i++) - { - $data[$i] = $line; - } - if (-f "/etc/mysql/my.cnf" && -r "/etc/mysql/my.cnf") - { - open(MY_CNF, "</etc/mysql/my.cnf") && (@tmp=<MY_CNF>) && close(MY_CNF); - } - for (; ($line = shift @tmp); $i++) - { - $data[$i] = $line; - } - if (defined($ENV{MYSQL_HOME}) && -f "$ENV{MYSQL_HOME}/my.cnf" && - -r "$ENV{MYSQL_HOME}/my.cnf") - { - open(MY_CNF, "<$ENV{MYSQL_HOME}/my.cnf") && (@tmp=<MY_CNF>) && - close(MY_CNF); - } - for (; ($line = shift @tmp); $i++) - { - $data[$i] = $line; - } - if (-f "$homedir/.my.cnf" && -r "$homedir/.my.cnf") - { - open(MY_CNF, "<$homedir/.my.cnf") && (@tmp=<MY_CNF>) && close(MY_CNF); - } - for (; ($line = shift @tmp); $i++) - { - $data[$i] = $line; - } - } - chomp @data; - # Make a list of the wanted group ids - if (defined($raw_gids)) - { - @pre_gids = split(',', $raw_gids); - } + my %gids; + my @groups; + if (defined($raw_gids)) { - for ($i = 0, $j = 0; defined($pre_gids[$i]); $i++) + # Make a hash of the wanted group ids + foreach my $raw_gid (split ',', $raw_gids) { - if ($pre_gids[$i] =~ m/^(\d+)$/) + # Match 123 or 123-456 + my ($start, $end) = ($raw_gid =~ /^\s*(\d+)(?:\s*-\s*(\d+))?\s*$/); + $end = $start if not defined $end; + if (not defined $start or $end < $start or $start < 0) { - $gids[$j] = $1; - $j++; + print "ABORT: Bad GNR: $raw_gid; see $my_progname --help\n"; + exit(1); } - elsif ($pre_gids[$i] =~ m/^(\d+)(\-)(\d+)$/) - { - for ($k = $1; $k <= $3; $k++) - { - $gids[$j] = $k; - $j++; - } - } - else + + foreach my $i ($start .. $end) { - print "ABORT: Bad GNR: $pre_gids[$i] See $my_progname --help\n"; - exit(1); + # Use $i + 0 to normalize numbers (002 + 0 -> 2) + $gids{$i + 0}= 1; } } } - # Sort the list of gids numerically in ascending order - @gids = sort {$a <=> $b} @gids; - # Remove non-positive integers and duplicates - for ($i = 0, $j = 0; defined($gids[$i]); $i++) - { - next if ($gids[$i] <= 0); - if (!$i || $prev_value != $gids[$i]) - { - $tmp2[$j] = $gids[$i]; - $j++; - } - $prev_value = $gids[$i]; - } - @gids = @tmp2; - # Find and return the wanted groups - for ($i = 0, $j = 0; defined($data[$i]); $i++) + + my @defaults_files = list_defaults_files(); + #warn "@{[sort keys %gids]} -> @defaults_files\n"; + foreach my $file (@defaults_files) { - if ($data[$i] =~ m/^(\s*\[\s*)(mysqld)(\d+)(\s*\]\s*)$/) + next unless open CONF, "< $file"; + + while (<CONF>) { - if (defined($raw_gids)) - { - for ($k = 0; defined($gids[$k]); $k++) - { - if ($gids[$k] == $3) - { - $groups[$j] = $2 . $3; - $j++; - } - } - } - else + if (/^\s*\[\s*(mysqld)(\d+)\s*\]\s*$/) { - $groups[$j] = $2 . $3; - $j++; + #warn "Found a group: $1$2\n"; + # Use $2 + 0 to normalize numbers (002 + 0 -> 2) + if (not defined($raw_gids) or $gids{$2 + 0}) + { + push @groups, "$1$2"; + } } } + + close CONF; } return @groups; } @@ -806,8 +740,16 @@ groups found will either be started, stopped, or reported. Note that syntax for specifying GNRs must appear without spaces. Options: ---config-file=... Alternative config file. - Using: $opt_config_file + +These options must be given before any others: +--no-defaults Do not read any defaults file +--defaults-file=... Read only this configuration file, do not read the + standard system-wide and user-specific files +--defaults-extra-file=... Read this configuration file in addition to the + standard system-wide and user-specific files +Using: @{[join ' ', @defaults_options]} + +--config-file=... Deprecated, please use --defaults-extra-file instead --example Give an example of a config file with extra information. --help Print this help and exit. --log=... Log file. Full path to and the name for the log file. NOTE: diff --git a/sql/item_func.cc b/sql/item_func.cc index 503b4362e7a..14a4c4dcf4b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -616,6 +616,14 @@ Item *Item_func::get_tmp_table_item(THD *thd) return copy_or_same(thd); } +double Item_int_func::val_real() +{ + DBUG_ASSERT(fixed == 1); + + return unsigned_flag ? (double) ((ulonglong) val_int()) : (double) val_int(); +} + + String *Item_int_func::val_str(String *str) { DBUG_ASSERT(fixed == 1); @@ -804,7 +812,10 @@ double Item_func_numhybrid::val_real() return result; } case INT_RESULT: - return (double)int_op(); + { + longlong result= int_op(); + return unsigned_flag ? (double) ((ulonglong) result) : (double) result; + } case REAL_RESULT: return real_op(); case STRING_RESULT: @@ -1341,6 +1352,8 @@ longlong Item_func_mod::int_op() DBUG_ASSERT(fixed == 1); longlong value= args[0]->val_int(); longlong val2= args[1]->val_int(); + longlong result; + if ((null_value= args[0]->null_value || args[1]->null_value)) return 0; /* purecov: inspected */ if (val2 == 0) @@ -1350,9 +1363,13 @@ longlong Item_func_mod::int_op() } if (args[0]->unsigned_flag) - return ((ulonglong) value) % val2; + result= args[1]->unsigned_flag ? + ((ulonglong) value) % ((ulonglong) val2) : ((ulonglong) value) % val2; + else + result= args[1]->unsigned_flag ? + value % ((ulonglong) val2) : value % val2; - return value % val2; + return result; } double Item_func_mod::real_op() @@ -1407,6 +1424,7 @@ void Item_func_mod::fix_length_and_dec() { Item_num_op::fix_length_and_dec(); maybe_null= 1; + unsigned_flag= args[0]->unsigned_flag; } @@ -1485,8 +1503,9 @@ double Item_func_abs::real_op() longlong Item_func_abs::int_op() { longlong value= args[0]->val_int(); - null_value= args[0]->null_value; - return value >= 0 ? value : -value; + if ((null_value= args[0]->null_value)) + return 0; + return (value >= 0) || unsigned_flag ? value : -value; } @@ -1507,6 +1526,7 @@ my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value) void Item_func_abs::fix_length_and_dec() { Item_func_num1::fix_length_and_dec(); + unsigned_flag= args[0]->unsigned_flag; } @@ -1881,6 +1901,10 @@ my_decimal *Item_func_floor::decimal_op(my_decimal *decimal_value) void Item_func_round::fix_length_and_dec() { + int decimals_to_set; + longlong val1; + bool val1_unsigned; + unsigned_flag= args[0]->unsigned_flag; if (!args[1]->const_item()) { @@ -1889,8 +1913,14 @@ void Item_func_round::fix_length_and_dec() hybrid_type= REAL_RESULT; return; } - - int decimals_to_set= max((int)args[1]->val_int(), 0); + + val1= args[1]->val_int(); + val1_unsigned= args[1]->unsigned_flag; + if (val1 < 0) + decimals_to_set= val1_unsigned ? INT_MAX : 0; + else + decimals_to_set= (val1 > INT_MAX) ? INT_MAX : (int) val1; + if (args[0]->decimals == NOT_FIXED_DEC) { max_length= args[0]->max_length; @@ -1907,10 +1937,9 @@ void Item_func_round::fix_length_and_dec() max_length= float_length(decimals); break; case INT_RESULT: - if (!decimals_to_set && - (truncate || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS))) + if ((!decimals_to_set && truncate) || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS)) { - int length_can_increase= test(!truncate && (args[1]->val_int() < 0)); + int length_can_increase= test(!truncate && (val1 < 0) && !val1_unsigned); max_length= args[0]->max_length + length_can_increase; /* Here we can keep INT_RESULT */ hybrid_type= INT_RESULT; @@ -1936,10 +1965,12 @@ void Item_func_round::fix_length_and_dec() } } -double my_double_round(double value, int dec, bool truncate) +double my_double_round(double value, longlong dec, bool dec_unsigned, + bool truncate) { double tmp; - uint abs_dec= abs(dec); + bool dec_negative= (dec < 0) && !dec_unsigned; + ulonglong abs_dec= dec_negative ? -dec : dec; /* tmp2 is here to avoid return the value with 80 bit precision This will fix that the test round(0.1,1) = round(0.1,1) is true @@ -1949,7 +1980,11 @@ double my_double_round(double value, int dec, bool truncate) tmp=(abs_dec < array_elements(log_10) ? log_10[abs_dec] : pow(10.0,(double) abs_dec)); - if (truncate) + if (dec_negative && isinf(tmp)) + tmp2= 0; + else if (!dec_negative && isinf(value * tmp)) + tmp2= value; + else if (truncate) { if (value >= 0) tmp2= dec < 0 ? floor(value/tmp)*tmp : floor(value*tmp)/tmp; @@ -1965,24 +2000,35 @@ double my_double_round(double value, int dec, bool truncate) double Item_func_round::real_op() { double value= args[0]->val_real(); - int dec= (int) args[1]->val_int(); if (!(null_value= args[0]->null_value || args[1]->null_value)) - return my_double_round(value, dec, truncate); + return my_double_round(value, args[1]->val_int(), args[1]->unsigned_flag, + truncate); return 0.0; } +/* + Rounds a given value to a power of 10 specified as the 'to' argument, + avoiding overflows when the value is close to the ulonglong range boundary. +*/ + +static inline ulonglong my_unsigned_round(ulonglong value, ulonglong to) +{ + ulonglong tmp= value / to * to; + return (value - tmp < (to >> 1)) ? tmp : tmp + to; +} + longlong Item_func_round::int_op() { longlong value= args[0]->val_int(); - int dec=(int) args[1]->val_int(); + longlong dec= args[1]->val_int(); decimals= 0; - uint abs_dec; + ulonglong abs_dec; if ((null_value= args[0]->null_value || args[1]->null_value)) return 0; - if (dec >= 0) + if ((dec >= 0) || args[1]->unsigned_flag) return value; // integer have not digits after point abs_dec= -dec; @@ -1994,21 +2040,12 @@ longlong Item_func_round::int_op() tmp= log_10_int[abs_dec]; if (truncate) - { - if (unsigned_flag) - value= (ulonglong(value)/tmp)*tmp; - else - value= (value/tmp)*tmp; - } + value= (unsigned_flag) ? + ((ulonglong) value / tmp) * tmp : (value / tmp) * tmp; else - { - if (unsigned_flag) - value= ((ulonglong(value)+(tmp>>1))/tmp)*tmp; - else if ( value >= 0) - value= ((value+(tmp>>1))/tmp)*tmp; - else - value= ((value-(tmp>>1))/tmp)*tmp; - } + value= (unsigned_flag || value >= 0) ? + my_unsigned_round((ulonglong) value, tmp) : + -(longlong) my_unsigned_round((ulonglong) -value, tmp); return value; } @@ -2016,14 +2053,18 @@ longlong Item_func_round::int_op() my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value) { my_decimal val, *value= args[0]->val_decimal(&val); - int dec=(int) args[1]->val_int(); - if (dec > 0) + longlong dec= args[1]->val_int(); + if (dec > 0 || (dec < 0 && args[1]->unsigned_flag)) { - decimals= min(dec, DECIMAL_MAX_SCALE); // to get correct output + dec= min((ulonglong) dec, DECIMAL_MAX_SCALE); + decimals= (uint8) dec; // to get correct output } + else if (dec < INT_MIN) + dec= INT_MIN; + if (!(null_value= (args[0]->null_value || args[1]->null_value || - my_decimal_round(E_DEC_FATAL_ERROR, value, dec, truncate, - decimal_value) > 1))) + my_decimal_round(E_DEC_FATAL_ERROR, value, (int) dec, + truncate, decimal_value) > 1))) return decimal_value; return 0; } diff --git a/sql/item_func.h b/sql/item_func.h index 635a409e0a2..037a2ee967b 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -278,7 +278,7 @@ public: { max_length= 21; } Item_int_func(List<Item> &list) :Item_func(list) { max_length= 21; } Item_int_func(THD *thd, Item_int_func *item) :Item_func(thd, item) {} - double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); } + double val_real(); String *val_str(String*str); enum Item_result result_type () const { return INT_RESULT; } void fix_length_and_dec() {} @@ -303,12 +303,6 @@ class Item_func_signed :public Item_int_func public: Item_func_signed(Item *a) :Item_int_func(a) {} const char *func_name() const { return "cast_as_signed"; } - double val_real() - { - double tmp= args[0]->val_real(); - null_value= args[0]->null_value; - return tmp; - } longlong val_int(); longlong val_int_from_str(int *error); void fix_length_and_dec() diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 1991526345c..f9a0f715985 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1995,7 +1995,7 @@ String *Item_func_format::val_str(String *str) double nr= args[0]->val_real(); if ((null_value=args[0]->null_value)) return 0; /* purecov: inspected */ - nr= my_double_round(nr, decimals, FALSE); + nr= my_double_round(nr, (longlong) decimals, FALSE, FALSE); /* Here default_charset() is right as this is not an automatic conversion */ str->set(nr,decimals, default_charset()); if (isnan(nr)) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 7e873dd7cc6..7ab683134e0 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1539,7 +1539,8 @@ ha_rows filesort(THD *thd, TABLE *form,struct st_sort_field *sortorder, ha_rows max_rows, ha_rows *examined_rows); void filesort_free_buffers(TABLE *table, bool full); void change_double_for_sort(double nr,byte *to); -double my_double_round(double value, int dec, bool truncate); +double my_double_round(double value, longlong dec, bool dec_unsigned, + bool truncate); int get_quick_record(SQL_SELECT *select); int calc_weekday(long daynr,bool sunday_first_day_of_week); uint calc_week(TIME *l_time, uint week_behaviour, uint *year); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6f953349c03..42d59a10712 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -42,6 +42,7 @@ static int copy_data_between_tables(TABLE *from,TABLE *to, static bool prepare_blob_field(THD *thd, create_field *sql_field); static bool check_engine(THD *thd, const char *table_name, enum db_type *new_engine); +static void set_tmp_file_path(char *buf, size_t bufsize, THD *thd); /* @@ -1681,11 +1682,7 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name, /* Check if table exists */ if (create_info->options & HA_LEX_CREATE_TMP_TABLE) { - my_snprintf(path, sizeof(path), "%s%s%lx_%lx_%x%s", - mysql_tmpdir, tmp_file_prefix, current_pid, thd->thread_id, - thd->tmp_table++, reg_ext); - if (lower_case_table_names) - my_casedn_str(files_charset_info, path); + set_tmp_file_path(path, sizeof(path), thd); create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE; } else @@ -2801,11 +2798,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, { if (find_temporary_table(thd, db, table_name)) goto table_exists; - my_snprintf(dst_path, sizeof(dst_path), "%s%s%lx_%lx_%x%s", - mysql_tmpdir, tmp_file_prefix, current_pid, - thd->thread_id, thd->tmp_table++, reg_ext); - if (lower_case_table_names) - my_casedn_str(files_charset_info, dst_path); + set_tmp_file_path(dst_path, sizeof(dst_path), thd); create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE; } else @@ -3316,6 +3309,12 @@ view_err: create_info->avg_row_length= table->s->avg_row_length; if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET)) create_info->default_table_charset= table->s->table_charset; + if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field) + { + /* Table has an autoincrement, copy value to new table */ + table->file->info(HA_STATUS_AUTO); + create_info->auto_increment_value= table->file->auto_increment_value; + } restore_record(table, s->default_values); // Empty record for DEFAULT List_iterator<Alter_drop> drop_it(alter_info->drop_list); @@ -4313,3 +4312,16 @@ static bool check_engine(THD *thd, const char *table_name, } return FALSE; } + +static void set_tmp_file_path(char *buf, size_t bufsize, THD *thd) +{ + char *p= strnmov(buf, mysql_tmpdir, bufsize); + my_snprintf(p, bufsize - (p - buf), "%s%lx_%lx_%x%s", + tmp_file_prefix, current_pid, + thd->thread_id, thd->tmp_table++, reg_ext); + if (lower_case_table_names) + { + /* Convert all except tmpdir to lower case */ + my_casedn_str(files_charset_info, p); + } +} diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 6f6c4538040..e17c71ae541 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1354,19 +1354,18 @@ bool multi_update::send_data(List<Item> ¬_used_values) memcpy((char*) tmp_table->field[0]->ptr, (char*) table->file->ref, table->file->ref_length); /* Write row, ignoring duplicated updates to a row */ - if ((error= tmp_table->file->write_row(tmp_table->record[0]))) + error= tmp_table->file->write_row(tmp_table->record[0]); + if (error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE) { - if (error != HA_ERR_FOUND_DUPP_KEY && - error != HA_ERR_FOUND_DUPP_UNIQUE && + if (error && create_myisam_from_heap(thd, tmp_table, - tmp_table_param + offset, error, 1)) - { - do_update=0; - DBUG_RETURN(1); // Not a table_is_full error - } - } - else + tmp_table_param + offset, error, 1)) + { + do_update= 0; + DBUG_RETURN(1); // Not a table_is_full error + } found++; + } } } DBUG_RETURN(0); |