Commit dc9b20a6 authored by unknown's avatar unknown

Merge quadxeon.mysql.com:/benchmarks/ext3/TOSAVE/tsmith/bk/50

into  quadxeon.mysql.com:/benchmarks/ext3/TOSAVE/tsmith/bk/maint/50


sql/item_func.h:
  Auto merged
parents 5352b41d f8274257
...@@ -1489,8 +1489,15 @@ static uint dump_routines_for_db(char *db) ...@@ -1489,8 +1489,15 @@ static uint dump_routines_for_db(char *db)
routine body of other routines that are not the creator of! routine body of other routines that are not the creator of!
*/ */
DBUG_PRINT("info",("length of body for %s row[2] '%s' is %d", DBUG_PRINT("info",("length of body for %s row[2] '%s' is %d",
routine_name, row[2], (int) strlen(row[2]))); routine_name, row[2] ? row[2] : "(null)",
if (strlen(row[2])) 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 *query_str= NULL;
char *definer_begin; char *definer_begin;
...@@ -1540,7 +1547,7 @@ static uint dump_routines_for_db(char *db) ...@@ -1540,7 +1547,7 @@ static uint dump_routines_for_db(char *db)
/* /*
we need to change sql_mode only for the CREATE we need to change sql_mode only for the CREATE
PROCEDURE/FUNCTION otherwise we may need to re-quote routine_name PROCEDURE/FUNCTION otherwise we may need to re-quote routine_name
*/; */
fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\"*/;;\n", fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\"*/;;\n",
row[1] /* sql_mode */); row[1] /* sql_mode */);
fprintf(sql_file, "/*!50003 %s */;;\n", fprintf(sql_file, "/*!50003 %s */;;\n",
......
...@@ -33,7 +33,20 @@ const char *default_dbug_option="d:t:o,/tmp/my_print_defaults.trace"; ...@@ -33,7 +33,20 @@ const char *default_dbug_option="d:t:o,/tmp/my_print_defaults.trace";
static struct my_option my_long_options[] = 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, (gptr*) &config_file, (gptr*) &config_file, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0, 0},
#ifdef DBUG_OFF #ifdef DBUG_OFF
...@@ -43,11 +56,11 @@ static struct my_option my_long_options[] = ...@@ -43,11 +56,11 @@ static struct my_option my_long_options[] =
{"debug", '#', "Output debug log", (gptr*) &default_dbug_option, {"debug", '#', "Output debug log", (gptr*) &default_dbug_option,
(gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
#endif #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, (gptr*) &config_file, (gptr*) &config_file, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0, 0},
{"defaults-extra-file", 'e', {"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, (gptr*) &my_defaults_extra_file, (gptr*) &my_defaults_extra_file, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"defaults-group-suffix", 'g', {"defaults-group-suffix", 'g',
...@@ -55,7 +68,7 @@ static struct my_option my_long_options[] = ...@@ -55,7 +68,7 @@ static struct my_option my_long_options[] =
(gptr*) &my_defaults_group_suffix, (gptr*) &my_defaults_group_suffix, (gptr*) &my_defaults_group_suffix, (gptr*) &my_defaults_group_suffix,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"extra-file", 'e', {"extra-file", 'e',
"Synonym for --defaults-extra-file.", "Deprecated. Synonym for --defaults-extra-file.",
(gptr*) &my_defaults_extra_file, (gptr*) &my_defaults_extra_file,
(gptr*) &my_defaults_extra_file, 0, GET_STR, (gptr*) &my_defaults_extra_file, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
...@@ -86,7 +99,7 @@ static void usage(my_bool version) ...@@ -86,7 +99,7 @@ static void usage(my_bool version)
my_print_help(my_long_options); my_print_help(my_long_options);
my_print_default_files(config_file); my_print_default_files(config_file);
my_print_variables(my_long_options); 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> #include <help_end.h>
......
...@@ -784,13 +784,20 @@ typedef SOCKET_SIZE_TYPE size_socket; ...@@ -784,13 +784,20 @@ typedef SOCKET_SIZE_TYPE size_socket;
#define SSIZE_MAX ((~((size_t) 0)) / 2) #define SSIZE_MAX ((~((size_t) 0)) / 2)
#endif #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) #if !defined(HAVE_ISINF)
/* The configure check for "isinf with math.h" has failed */ /* The configure check for "isinf with math.h" has failed */
#ifdef isinf #ifdef isinf
#undef isinf #undef isinf
#endif #endif
/* Define isinf to never say that X is infinite */ #define isinf(X) (!finite(X) && !isnan(X))
#define isinf(X) 0
#endif #endif
/* Define missing math constants. */ /* Define missing math constants. */
......
--require r/lowercase1.require
--disable_query_log
show variables like 'lower_case_table_names';
--enable_query_log
...@@ -238,7 +238,7 @@ sub mtr_report_stats ($) { ...@@ -238,7 +238,7 @@ sub mtr_report_stats ($) {
} }
if (!$::opt_extern) if (!$::opt_extern)
{ {
print "The servers where restarted $tot_restarts times\n"; print "The servers were restarted $tot_restarts times\n";
} }
if ( $::opt_timer ) if ( $::opt_timer )
...@@ -357,7 +357,7 @@ sub mtr_report_stats ($) { ...@@ -357,7 +357,7 @@ sub mtr_report_stats ($) {
if ( $tot_failed != 0 || $found_problems) if ( $tot_failed != 0 || $found_problems)
{ {
mtr_error("there where failing test cases"); mtr_error("there were failing test cases");
} }
} }
......
...@@ -860,3 +860,27 @@ ALTER TABLE t1 ADD d INT; ...@@ -860,3 +860,27 @@ ALTER TABLE t1 ADD d INT;
ALTER TABLE t1 ADD KEY (d(20)); 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 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; 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;
...@@ -143,9 +143,6 @@ select format(col2,6) from t1 where col1=7; ...@@ -143,9 +143,6 @@ select format(col2,6) from t1 where col1=7;
format(col2,6) format(col2,6)
1,234,567,890,123,456.123450 1,234,567,890,123,456.123450
drop table t1; drop table t1;
select round(150, 2);
round(150, 2)
150.00
select ceil(0.09); select ceil(0.09);
ceil(0.09) ceil(0.09)
1 1
...@@ -156,11 +153,11 @@ create table t1 select round(1, 6); ...@@ -156,11 +153,11 @@ create table t1 select round(1, 6);
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( 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 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t1; select * from t1;
round(1, 6) round(1, 6)
1.000000 1
drop table t1; drop table t1;
select abs(-2) * -2; select abs(-2) * -2;
abs(-2) * -2 abs(-2) * -2
...@@ -238,3 +235,91 @@ format(t2.f2-t2.f1+1,0) ...@@ -238,3 +235,91 @@ format(t2.f2-t2.f1+1,0)
10,000 10,000
drop table t1, t2; drop table t1, t2;
set names default; 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
Variable_name Value
lower_case_table_names 1
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;
...@@ -3283,5 +3283,32 @@ drop database bug23491_original; ...@@ -3283,5 +3283,32 @@ drop database bug23491_original;
drop database bug23491_restore; drop database bug23491_restore;
use test; 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 # End of 5.0 tests
# #
...@@ -763,7 +763,7 @@ truncate(99999999999999999999999999999999999999,31) ...@@ -763,7 +763,7 @@ truncate(99999999999999999999999999999999999999,31)
99999999999999999999999999999999999999.000000000000000000000000000000 99999999999999999999999999999999999999.000000000000000000000000000000
select truncate(99.999999999999999999999999999999999999,31); select truncate(99.999999999999999999999999999999999999,31);
truncate(99.999999999999999999999999999999999999,31) truncate(99.999999999999999999999999999999999999,31)
100.000000000000000000000000000000 99.999999999999999999999999999999
select truncate(99999999999999999999999999999999999999,-31); select truncate(99999999999999999999999999999999999999,-31);
truncate(99999999999999999999999999999999999999,-31) truncate(99999999999999999999999999999999999999,-31)
99999990000000000000000000000000000000 99999990000000000000000000000000000000
......
...@@ -457,3 +457,38 @@ a quux ...@@ -457,3 +457,38 @@ a quux
2 0.100000000000000000000000000000 2 0.100000000000000000000000000000
3 NULL 3 NULL
DROP TABLE t1; 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
...@@ -636,3 +636,29 @@ ALTER TABLE t1 ADD d INT; ...@@ -636,3 +636,29 @@ ALTER TABLE t1 ADD d INT;
ALTER TABLE t1 ADD KEY (d(20)); ALTER TABLE t1 ADD KEY (d(20));
DROP TABLE t1; 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;
...@@ -82,11 +82,6 @@ select format(col2,6) from t1 where col1=7; ...@@ -82,11 +82,6 @@ select format(col2,6) from t1 where col1=7;
drop table t1; drop table t1;
#
# Bug #10083 (round doesn't increase decimals)
#
select round(150, 2);
# #
# Bug @10632 (Ceiling function returns wrong answer) # Bug @10632 (Ceiling function returns wrong answer)
# #
...@@ -177,3 +172,37 @@ select format(t2.f2-t2.f1+1,0) from t1,t2 ...@@ -177,3 +172,37 @@ select format(t2.f2-t2.f1+1,0) from t1,t2
where t1.f2 = t2.f3 order by t1.f1; where t1.f2 = t2.f3 order by t1.f1;
drop table t1, t2; drop table t1, t2;
set names default; 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
--lower-case-table-names=1
--tmpdir=$MYSQLTEST_VARDIR/tmp/MixedCase
# 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"/*
--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;
...@@ -1495,6 +1495,41 @@ drop database bug23491_original; ...@@ -1495,6 +1495,41 @@ drop database bug23491_original;
drop database bug23491_restore; drop database bug23491_restore;
use test; 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 #
--echo # End of 5.0 tests --echo # End of 5.0 tests
--echo # --echo #
...@@ -376,3 +376,58 @@ INSERT INTO t1( a ) ...@@ -376,3 +376,58 @@ INSERT INTO t1( a )
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE 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
...@@ -877,8 +877,8 @@ void my_print_default_files(const char *conf_file) ...@@ -877,8 +877,8 @@ void my_print_default_files(const char *conf_file)
fputs(name,stdout); fputs(name,stdout);
} }
} }
puts("");
} }
puts("");
} }
void print_defaults(const char *conf_file, const char **groups) void print_defaults(const char *conf_file, const char **groups)
......
...@@ -111,6 +111,11 @@ int my_copy(const char *from, const char *to, myf MyFlags) ...@@ -111,6 +111,11 @@ int my_copy(const char *from, const char *to, myf MyFlags)
err: err:
if (from_file >= 0) VOID(my_close(from_file,MyFlags)); 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); DBUG_RETURN(-1);
} /* my_copy */ } /* my_copy */
...@@ -79,7 +79,10 @@ parse_arguments() { ...@@ -79,7 +79,10 @@ parse_arguments() {
then then
# This sed command makes sure that any special chars are quoted, # This sed command makes sure that any special chars are quoted,
# so the arg gets passed exactly to the server. # 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 fi
;; ;;
esac esac
...@@ -151,6 +154,7 @@ else ...@@ -151,6 +154,7 @@ else
if test -f $i/$fill_help_tables if test -f $i/$fill_help_tables
then then
pkgdatadir=$i pkgdatadir=$i
break
fi fi
done done
......
...@@ -4,9 +4,10 @@ use Getopt::Long; ...@@ -4,9 +4,10 @@ use Getopt::Long;
use POSIX qw(strftime); use POSIX qw(strftime);
$|=1; $|=1;
$VER="2.15"; $VER="2.16";
my @defaults_options; # Leading --no-defaults, --defaults-file, etc.
$opt_config_file = undef();
$opt_example = 0; $opt_example = 0;
$opt_help = 0; $opt_help = 0;
$opt_log = undef(); $opt_log = undef();
...@@ -49,54 +50,52 @@ sub main ...@@ -49,54 +50,52 @@ sub main
print "MySQL distribution.\n"; print "MySQL distribution.\n";
$my_print_defaults_exists= 0; $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)) # Put it at the beginning of the list, so it has lower precedence
{ # than a correct --defaults-extra-file option
die "Option config-file requires an argument\n";
unshift @defaults_options, "--defaults-extra-file=$1";
} }
elsif (!( -e $1 && -r $1))
{
die "Option file '$1' doesn't exists, or is not readable\n";
} }
else
{ foreach (@defaults_options)
$opt_config_file= $1;
if (!($opt_config_file =~ m/\//))
{ {
# No path. Use current working directory $_ = quote_shell_word($_);
$opt_config_file= "./" . $opt_config_file;
}
}
} }
}
my $com= "my_print_defaults "; # Add [mysqld_multi] options to front of @ARGV, ready for GetOptions()
$com.= "--config-file=$opt_config_file " if (defined($opt_config_file)); unshift @ARGV, defaults_for_group('mysqld_multi');
$com.= "mysqld_multi";
my @defops = `$com`; # The --config-file option can be ignored; if passed on the command
chop @defops; # line, it's already handled; if specified in the configuration file,
splice @ARGV, 0, 0, @defops; # it's redundant and not useful
} @ARGV= grep { not /^--config-file=/ } @ARGV;
if (!GetOptions("help","example","version","mysqld=s","mysqladmin=s",
"config-file=s","user=s","password=s","log=s","no-log", # We've already handled --no-defaults, --defaults-file, etc.
"tcp-ip", "silent","verbose")) if (!GetOptions("help", "example", "version", "mysqld=s", "mysqladmin=s",
"user=s", "password=s", "log=s", "no-log",
"tcp-ip", "silent", "verbose"))
{ {
$flag_exit= 1; $flag_exit= 1;
} }
if (defined($opt_config_file) && !($opt_config_file =~ m/\//))
{
# No path. Use current working directory
$opt_config_file= "./" . $opt_config_file;
}
usage() if ($opt_help); usage() if ($opt_help);
if ($opt_verbose && $opt_silent) 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"; print "will be disabled\nand some will be enabled.\n\n";
} }
...@@ -168,53 +167,44 @@ sub main ...@@ -168,53 +167,44 @@ sub main
} }
} }
#### #
#### Quote option argument. Add double quotes around the argument # Quote word for shell
#### 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.
####
sub quote_opt_arg sub quote_shell_word
{ {
my ($option)= @_; my ($option)= @_;
if ($option =~ m/(\-\-[a-zA-Z0-9\_\-]+)=(.*)/) $option =~ s!([^\w=./-])!\\$1!g;
{
$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;
}
return $option; 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 #### 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 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[=](.*)/)
{ {
if (-d "$1" && -w "$1") if ($opt =~ m/^--datadir=(.*)/ && -d "$1" && -w "$1")
{ {
$logdir= $1; $logdir= $1;
} }
} }
}
}
if (!defined($logdir)) if (!defined($logdir))
{ {
$logdir= "@datadir@" if (-d "@datadir@" && -w "@datadir@"); $logdir= "@datadir@" if (-d "@datadir@" && -w "@datadir@");
...@@ -303,11 +293,7 @@ sub start_mysqlds() ...@@ -303,11 +293,7 @@ sub start_mysqlds()
@groups = &find_groups($groupids); @groups = &find_groups($groupids);
for ($i = 0; defined($groups[$i]); $i++) for ($i = 0; defined($groups[$i]); $i++)
{ {
$com = "my_print_defaults"; @options = defaults_for_group($groups[$i]);
$com.= defined($opt_config_file) ? " --config-file=$opt_config_file" : "";
$com.= " $groups[$i]";
@options = `$com`;
chop @options;
$mysqld_found= 1; # The default $mysqld_found= 1; # The default
$mysqld_found= 0 if (!length($mysqld)); $mysqld_found= 0 if (!length($mysqld));
...@@ -326,7 +312,7 @@ sub start_mysqlds() ...@@ -326,7 +312,7 @@ sub start_mysqlds()
} }
else else
{ {
$options[$j]= quote_opt_arg($options[$j]); $options[$j]= quote_shell_word($options[$j]);
$tmp.= " $options[$j]"; $tmp.= " $options[$j]";
} }
} }
...@@ -401,11 +387,7 @@ sub get_mysqladmin_options ...@@ -401,11 +387,7 @@ sub get_mysqladmin_options
my ($i, @groups)= @_; my ($i, @groups)= @_;
my ($mysqladmin_found, $com, $tmp, $j); my ($mysqladmin_found, $com, $tmp, $j);
$com = "my_print_defaults"; @options = defaults_for_group($groups[$i]);
$com.= defined($opt_config_file) ? " --config-file=$opt_config_file" : "";
$com.= " $groups[$i]";
@options = `$com`;
chop @options;
$mysqladmin_found= 1; # The default $mysqladmin_found= 1; # The default
$mysqladmin_found= 0 if (!length($mysqladmin)); $mysqladmin_found= 0 if (!length($mysqladmin));
...@@ -445,129 +427,81 @@ sub get_mysqladmin_options ...@@ -445,129 +427,81 @@ sub get_mysqladmin_options
return $com; return $com;
} }
#### # Return a list of option files which can be opened. Similar, but not
#### Find groups. Takes the valid group numbers as an argument, parses # identical, to behavior of my_search_option_files()
#### them, puts them in the ascending order, removes duplicates and sub list_defaults_files
#### returns the wanted groups accordingly. {
#### 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 sub find_groups
{ {
my ($raw_gids) = @_; 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' my %gids;
if (defined($opt_config_file)) my @groups;
{
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);
}
if (defined($raw_gids)) 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; print "ABORT: Bad GNR: $raw_gid; see $my_progname --help\n";
$j++;
}
elsif ($pre_gids[$i] =~ m/^(\d+)(\-)(\d+)$/)
{
for ($k = $1; $k <= $3; $k++)
{
$gids[$j] = $k;
$j++;
}
}
else
{
print "ABORT: Bad GNR: $pre_gids[$i] See $my_progname --help\n";
exit(1); exit(1);
} }
}
} foreach my $i ($start .. $end)
# 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]; # Use $i + 0 to normalize numbers (002 + 0 -> 2)
$j++; $gids{$i + 0}= 1;
} }
$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";
if ($data[$i] =~ m/^(\s*\[\s*)(mysqld)(\d+)(\s*\]\s*)$/) foreach my $file (@defaults_files)
{ {
if (defined($raw_gids)) next unless open CONF, "< $file";
while (<CONF>)
{ {
for ($k = 0; defined($gids[$k]); $k++) if (/^\s*\[\s*(mysqld)(\d+)\s*\]\s*$/)
{ {
if ($gids[$k] == $3) #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})
{ {
$groups[$j] = $2 . $3; push @groups, "$1$2";
$j++;
} }
} }
} }
else
{ close CONF;
$groups[$j] = $2 . $3;
$j++;
}
}
} }
return @groups; return @groups;
} }
...@@ -806,8 +740,16 @@ groups found will either be started, stopped, or reported. Note that ...@@ -806,8 +740,16 @@ groups found will either be started, stopped, or reported. Note that
syntax for specifying GNRs must appear without spaces. syntax for specifying GNRs must appear without spaces.
Options: 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. --example Give an example of a config file with extra information.
--help Print this help and exit. --help Print this help and exit.
--log=... Log file. Full path to and the name for the log file. NOTE: --log=... Log file. Full path to and the name for the log file. NOTE:
......
...@@ -616,6 +616,14 @@ Item *Item_func::get_tmp_table_item(THD *thd) ...@@ -616,6 +616,14 @@ Item *Item_func::get_tmp_table_item(THD *thd)
return copy_or_same(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) String *Item_int_func::val_str(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
...@@ -804,7 +812,10 @@ double Item_func_numhybrid::val_real() ...@@ -804,7 +812,10 @@ double Item_func_numhybrid::val_real()
return result; return result;
} }
case INT_RESULT: case INT_RESULT:
return (double)int_op(); {
longlong result= int_op();
return unsigned_flag ? (double) ((ulonglong) result) : (double) result;
}
case REAL_RESULT: case REAL_RESULT:
return real_op(); return real_op();
case STRING_RESULT: case STRING_RESULT:
...@@ -1341,6 +1352,8 @@ longlong Item_func_mod::int_op() ...@@ -1341,6 +1352,8 @@ longlong Item_func_mod::int_op()
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
longlong value= args[0]->val_int(); longlong value= args[0]->val_int();
longlong val2= args[1]->val_int(); longlong val2= args[1]->val_int();
longlong result;
if ((null_value= args[0]->null_value || args[1]->null_value)) if ((null_value= args[0]->null_value || args[1]->null_value))
return 0; /* purecov: inspected */ return 0; /* purecov: inspected */
if (val2 == 0) if (val2 == 0)
...@@ -1350,9 +1363,13 @@ longlong Item_func_mod::int_op() ...@@ -1350,9 +1363,13 @@ longlong Item_func_mod::int_op()
} }
if (args[0]->unsigned_flag) 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() double Item_func_mod::real_op()
...@@ -1407,6 +1424,7 @@ void Item_func_mod::fix_length_and_dec() ...@@ -1407,6 +1424,7 @@ void Item_func_mod::fix_length_and_dec()
{ {
Item_num_op::fix_length_and_dec(); Item_num_op::fix_length_and_dec();
maybe_null= 1; maybe_null= 1;
unsigned_flag= args[0]->unsigned_flag;
} }
...@@ -1485,8 +1503,9 @@ double Item_func_abs::real_op() ...@@ -1485,8 +1503,9 @@ double Item_func_abs::real_op()
longlong Item_func_abs::int_op() longlong Item_func_abs::int_op()
{ {
longlong value= args[0]->val_int(); longlong value= args[0]->val_int();
null_value= args[0]->null_value; if ((null_value= args[0]->null_value))
return value >= 0 ? value : -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) ...@@ -1507,6 +1526,7 @@ my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value)
void Item_func_abs::fix_length_and_dec() void Item_func_abs::fix_length_and_dec()
{ {
Item_func_num1::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) ...@@ -1881,6 +1901,10 @@ my_decimal *Item_func_floor::decimal_op(my_decimal *decimal_value)
void Item_func_round::fix_length_and_dec() void Item_func_round::fix_length_and_dec()
{ {
int decimals_to_set;
longlong val1;
bool val1_unsigned;
unsigned_flag= args[0]->unsigned_flag; unsigned_flag= args[0]->unsigned_flag;
if (!args[1]->const_item()) if (!args[1]->const_item())
{ {
...@@ -1890,7 +1914,13 @@ void Item_func_round::fix_length_and_dec() ...@@ -1890,7 +1914,13 @@ void Item_func_round::fix_length_and_dec()
return; 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) if (args[0]->decimals == NOT_FIXED_DEC)
{ {
max_length= args[0]->max_length; max_length= args[0]->max_length;
...@@ -1907,10 +1937,9 @@ void Item_func_round::fix_length_and_dec() ...@@ -1907,10 +1937,9 @@ void Item_func_round::fix_length_and_dec()
max_length= float_length(decimals); max_length= float_length(decimals);
break; break;
case INT_RESULT: case INT_RESULT:
if (!decimals_to_set && if ((!decimals_to_set && truncate) || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS))
(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; max_length= args[0]->max_length + length_can_increase;
/* Here we can keep INT_RESULT */ /* Here we can keep INT_RESULT */
hybrid_type= INT_RESULT; hybrid_type= INT_RESULT;
...@@ -1936,10 +1965,12 @@ void Item_func_round::fix_length_and_dec() ...@@ -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; 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 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 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) ...@@ -1949,7 +1980,11 @@ double my_double_round(double value, int dec, bool truncate)
tmp=(abs_dec < array_elements(log_10) ? tmp=(abs_dec < array_elements(log_10) ?
log_10[abs_dec] : pow(10.0,(double) abs_dec)); 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) if (value >= 0)
tmp2= dec < 0 ? floor(value/tmp)*tmp : floor(value*tmp)/tmp; 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) ...@@ -1965,24 +2000,35 @@ double my_double_round(double value, int dec, bool truncate)
double Item_func_round::real_op() double Item_func_round::real_op()
{ {
double value= args[0]->val_real(); double value= args[0]->val_real();
int dec= (int) args[1]->val_int();
if (!(null_value= args[0]->null_value || args[1]->null_value)) 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; 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 Item_func_round::int_op()
{ {
longlong value= args[0]->val_int(); longlong value= args[0]->val_int();
int dec=(int) args[1]->val_int(); longlong dec= args[1]->val_int();
decimals= 0; decimals= 0;
uint abs_dec; ulonglong abs_dec;
if ((null_value= args[0]->null_value || args[1]->null_value)) if ((null_value= args[0]->null_value || args[1]->null_value))
return 0; return 0;
if (dec >= 0) if ((dec >= 0) || args[1]->unsigned_flag)
return value; // integer have not digits after point return value; // integer have not digits after point
abs_dec= -dec; abs_dec= -dec;
...@@ -1994,21 +2040,12 @@ longlong Item_func_round::int_op() ...@@ -1994,21 +2040,12 @@ longlong Item_func_round::int_op()
tmp= log_10_int[abs_dec]; tmp= log_10_int[abs_dec];
if (truncate) if (truncate)
{ value= (unsigned_flag) ?
if (unsigned_flag) ((ulonglong) value / tmp) * tmp : (value / tmp) * tmp;
value= (ulonglong(value)/tmp)*tmp;
else else
value= (value/tmp)*tmp; value= (unsigned_flag || value >= 0) ?
} my_unsigned_round((ulonglong) value, tmp) :
else -(longlong) my_unsigned_round((ulonglong) -value, tmp);
{
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;
}
return value; return value;
} }
...@@ -2016,14 +2053,18 @@ longlong Item_func_round::int_op() ...@@ -2016,14 +2053,18 @@ longlong Item_func_round::int_op()
my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value) my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value)
{ {
my_decimal val, *value= args[0]->val_decimal(&val); my_decimal val, *value= args[0]->val_decimal(&val);
int dec=(int) args[1]->val_int(); longlong dec= args[1]->val_int();
if (dec > 0) 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 || if (!(null_value= (args[0]->null_value || args[1]->null_value ||
my_decimal_round(E_DEC_FATAL_ERROR, value, dec, truncate, my_decimal_round(E_DEC_FATAL_ERROR, value, (int) dec,
decimal_value) > 1))) truncate, decimal_value) > 1)))
return decimal_value; return decimal_value;
return 0; return 0;
} }
......
...@@ -278,7 +278,7 @@ class Item_int_func :public Item_func ...@@ -278,7 +278,7 @@ class Item_int_func :public Item_func
{ max_length= 21; } { max_length= 21; }
Item_int_func(List<Item> &list) :Item_func(list) { 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) {} 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); String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; } enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec() {} void fix_length_and_dec() {}
...@@ -303,12 +303,6 @@ class Item_func_signed :public Item_int_func ...@@ -303,12 +303,6 @@ class Item_func_signed :public Item_int_func
public: public:
Item_func_signed(Item *a) :Item_int_func(a) {} Item_func_signed(Item *a) :Item_int_func(a) {}
const char *func_name() const { return "cast_as_signed"; } 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();
longlong val_int_from_str(int *error); longlong val_int_from_str(int *error);
void fix_length_and_dec() void fix_length_and_dec()
......
...@@ -1995,7 +1995,7 @@ String *Item_func_format::val_str(String *str) ...@@ -1995,7 +1995,7 @@ String *Item_func_format::val_str(String *str)
double nr= args[0]->val_real(); double nr= args[0]->val_real();
if ((null_value=args[0]->null_value)) if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */ 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 */ /* Here default_charset() is right as this is not an automatic conversion */
str->set(nr,decimals, default_charset()); str->set(nr,decimals, default_charset());
if (isnan(nr)) if (isnan(nr))
......
...@@ -1539,7 +1539,8 @@ ha_rows filesort(THD *thd, TABLE *form,struct st_sort_field *sortorder, ...@@ -1539,7 +1539,8 @@ ha_rows filesort(THD *thd, TABLE *form,struct st_sort_field *sortorder,
ha_rows max_rows, ha_rows *examined_rows); ha_rows max_rows, ha_rows *examined_rows);
void filesort_free_buffers(TABLE *table, bool full); void filesort_free_buffers(TABLE *table, bool full);
void change_double_for_sort(double nr,byte *to); 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 get_quick_record(SQL_SELECT *select);
int calc_weekday(long daynr,bool sunday_first_day_of_week); int calc_weekday(long daynr,bool sunday_first_day_of_week);
uint calc_week(TIME *l_time, uint week_behaviour, uint *year); uint calc_week(TIME *l_time, uint week_behaviour, uint *year);
......
...@@ -42,6 +42,7 @@ static int copy_data_between_tables(TABLE *from,TABLE *to, ...@@ -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 prepare_blob_field(THD *thd, create_field *sql_field);
static bool check_engine(THD *thd, const char *table_name, static bool check_engine(THD *thd, const char *table_name,
enum db_type *new_engine); 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, ...@@ -1681,11 +1682,7 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
/* Check if table exists */ /* Check if table exists */
if (create_info->options & HA_LEX_CREATE_TMP_TABLE) if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
{ {
my_snprintf(path, sizeof(path), "%s%s%lx_%lx_%x%s", set_tmp_file_path(path, sizeof(path), thd);
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);
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE; create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
} }
else else
...@@ -2801,11 +2798,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, ...@@ -2801,11 +2798,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
{ {
if (find_temporary_table(thd, db, table_name)) if (find_temporary_table(thd, db, table_name))
goto table_exists; goto table_exists;
my_snprintf(dst_path, sizeof(dst_path), "%s%s%lx_%lx_%x%s", set_tmp_file_path(dst_path, sizeof(dst_path), thd);
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);
create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE; create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
} }
else else
...@@ -3316,6 +3309,12 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -3316,6 +3309,12 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
create_info->avg_row_length= table->s->avg_row_length; create_info->avg_row_length= table->s->avg_row_length;
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET)) if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
create_info->default_table_charset= table->s->table_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 restore_record(table, s->default_values); // Empty record for DEFAULT
List_iterator<Alter_drop> drop_it(alter_info->drop_list); List_iterator<Alter_drop> drop_it(alter_info->drop_list);
...@@ -4313,3 +4312,16 @@ static bool check_engine(THD *thd, const char *table_name, ...@@ -4313,3 +4312,16 @@ static bool check_engine(THD *thd, const char *table_name,
} }
return FALSE; 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);
}
}
...@@ -1354,21 +1354,20 @@ bool multi_update::send_data(List<Item> &not_used_values) ...@@ -1354,21 +1354,20 @@ bool multi_update::send_data(List<Item> &not_used_values)
memcpy((char*) tmp_table->field[0]->ptr, memcpy((char*) tmp_table->field[0]->ptr,
(char*) table->file->ref, table->file->ref_length); (char*) table->file->ref, table->file->ref_length);
/* Write row, ignoring duplicated updates to a row */ /* 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 && if (error &&
error != HA_ERR_FOUND_DUPP_UNIQUE &&
create_myisam_from_heap(thd, tmp_table, create_myisam_from_heap(thd, tmp_table,
tmp_table_param + offset, error, 1)) tmp_table_param + offset, error, 1))
{ {
do_update=0; do_update= 0;
DBUG_RETURN(1); // Not a table_is_full error DBUG_RETURN(1); // Not a table_is_full error
} }
}
else
found++; found++;
} }
} }
}
DBUG_RETURN(0); DBUG_RETURN(0);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment