diff options
73 files changed, 1215 insertions, 259 deletions
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index fb2071ce10f..3350bfa17a7 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -206,6 +206,7 @@ static void dbDisconnect(char *host); static void DBerror(MYSQL *mysql, const char *when); static void safe_exit(int error); static void print_result(); +static uint fixed_name_length(const char *name); static char *fix_table_name(char *dest, char *src); int what_to_do = 0; @@ -438,14 +439,14 @@ static int process_selected_tables(char *db, char **table_names, int tables) { /* We need table list in form `a`, `b`, `c` - that's why we need 4 more chars added to to each table name + that's why we need 2 more chars added to to each table name space is for more readable output in logs and in case of error */ char *table_names_comma_sep, *end; int i, tot_length = 0; for (i = 0; i < tables; i++) - tot_length += strlen(*(table_names + i)) + 4; + tot_length+= fixed_name_length(*(table_names + i)) + 2; if (!(table_names_comma_sep = (char *) my_malloc((sizeof(char) * tot_length) + 4, MYF(MY_WME)))) @@ -463,23 +464,46 @@ static int process_selected_tables(char *db, char **table_names, int tables) } else for (; tables > 0; tables--, table_names++) - handle_request_for_tables(*table_names, strlen(*table_names)); + handle_request_for_tables(*table_names, fixed_name_length(*table_names)); return 0; } /* process_selected_tables */ -static char *fix_table_name(char *dest, char *src) +static uint fixed_name_length(const char *name) { - char *db_sep; + const char *p; + uint extra_length= 2; /* count the first/last backticks */ + + for (p= name; *p; p++) + { + if (*p == '`') + extra_length++; + else if (*p == '.') + extra_length+= 2; + } + return (p - name) + extra_length; +} + +static char *fix_table_name(char *dest, char *src) +{ *dest++= '`'; - if ((db_sep= strchr(src, '.'))) + for (; *src; src++) { - dest= strmake(dest, src, (uint) (db_sep - src)); - dest= strmov(dest, "`.`"); - src= db_sep + 1; + switch (*src) { + case '.': /* add backticks around '.' */ + *dest++= '`'; + *dest++= '.'; + *dest++= '`'; + break; + case '`': /* escape backtick character */ + *dest++= '`'; + /* fall through */ + default: + *dest++= *src; + } } - dest= strxmov(dest, src, "`", NullS); + *dest++= '`'; return dest; } @@ -500,7 +524,7 @@ static int process_all_tables_in_db(char *database) { /* We need table list in form `a`, `b`, `c` - that's why we need 4 more chars added to to each table name + that's why we need 2 more chars added to to each table name space is for more readable output in logs and in case of error */ @@ -508,7 +532,7 @@ static int process_all_tables_in_db(char *database) uint tot_length = 0; while ((row = mysql_fetch_row(res))) - tot_length += strlen(row[0]) + 4; + tot_length+= fixed_name_length(row[0]) + 2; mysql_data_seek(res, 0); if (!(tables=(char *) my_malloc(sizeof(char)*tot_length+4, MYF(MY_WME)))) @@ -533,10 +557,13 @@ static int process_all_tables_in_db(char *database) else { while ((row = mysql_fetch_row(res))) - /* Skip tables with an engine of NULL (probably a view). */ - if (row[1]) + /* + Skip tables with an engine of NULL (probably a view) + if we don't perform renaming. + */ + if (row[1] || what_to_do == DO_UPGRADE) { - handle_request_for_tables(row[0], strlen(row[0])); + handle_request_for_tables(row[0], fixed_name_length(row[0])); } } mysql_free_result(res); @@ -826,7 +853,7 @@ int main(int argc, char **argv) for (i = 0; i < tables4repair.elements ; i++) { char *name= (char*) dynamic_array_ptr(&tables4repair, i); - handle_request_for_tables(name, strlen(name)); + handle_request_for_tables(name, fixed_name_length(name)); } } end: diff --git a/client/mysqldump.c b/client/mysqldump.c index f5362b272cd..01b484e924e 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -420,8 +420,12 @@ static struct my_option my_long_options[] = "Creates a consistent snapshot by dumping all tables in a single " "transaction. Works ONLY for tables stored in storage engines which " "support multiversioning (currently only InnoDB does); the dump is NOT " - "guaranteed to be consistent for other storage engines. Option " - "automatically turns off --lock-tables.", + "guaranteed to be consistent for other storage engines. " + "While a --single-transaction dump is in process, to ensure a valid " + "dump file (correct table contents and binary log position), no other " + "connection should use the following statements: ALTER TABLE, DROP " + "TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not " + "isolated from them. Option automatically turns off --lock-tables.", (uchar**) &opt_single_transaction, (uchar**) &opt_single_transaction, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"dump-date", OPT_DUMP_DATE, "Put a dump date to the end of the output.", diff --git a/client/mysqltest.c b/client/mysqltest.c index 04226719888..cca2420d498 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -2670,7 +2670,7 @@ void do_copy_file(struct st_command *command) command command handle DESCRIPTION - chmod_file <octal> <file_name> + chmod <octal> <file_name> Change file permission of <file_name> */ diff --git a/include/my_base.h b/include/my_base.h index c2eb6a040c1..947f7695215 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -250,6 +250,8 @@ enum ha_base_keytype { HA_BINARY_PACK_KEY | HA_FULLTEXT | HA_UNIQUE_CHECK | \ HA_SPATIAL | HA_NULL_ARE_EQUAL | HA_GENERATED_KEY) +#define HA_KEY_HAS_PART_KEY_SEG 65536 /* Key contains partial segments */ + /* Automatic bits in key-flag */ #define HA_SPACE_PACK_USED 4 /* Test for if SPACE_PACK used */ diff --git a/include/my_sys.h b/include/my_sys.h index 7ae05bb96f7..e13c4cde78b 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -712,8 +712,10 @@ extern sig_handler my_set_alarm_variable(int signo); extern void my_string_ptr_sort(uchar *base, uint items, size_t size); extern void radixsort_for_str_ptr(uchar* base[], uint number_of_elements, size_t size_of_element,uchar *buffer[]); -extern qsort_t qsort2(void *base_ptr, size_t total_elems, size_t size, - qsort2_cmp cmp, void *cmp_argument); +extern qsort_t my_qsort(void *base_ptr, size_t total_elems, size_t size, + qsort_cmp cmp); +extern qsort_t my_qsort2(void *base_ptr, size_t total_elems, size_t size, + qsort2_cmp cmp, void *cmp_argument); extern qsort2_cmp get_ptr_compare(size_t); void my_store_ptr(uchar *buff, size_t pack_length, my_off_t pos); my_off_t my_get_ptr(uchar *ptr, size_t pack_length); @@ -784,7 +786,7 @@ extern int get_index_dynamic(DYNAMIC_ARRAY *array, uchar * element); #define dynamic_element(array,array_index,type) ((type)((array)->buffer) +(array_index)) #define push_dynamic(A,B) insert_dynamic((A),(B)) #define reset_dynamic(array) ((array)->elements= 0) -#define sort_dynamic(A,cmp) qsort((A)->buffer, (A)->elements, (A)->size_of_element, (cmp)) +#define sort_dynamic(A,cmp) my_qsort((A)->buffer, (A)->elements, (A)->size_of_element, (cmp)) extern my_bool init_dynamic_string(DYNAMIC_STRING *str, const char *init_str, size_t init_alloc,size_t alloc_increment); diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt index 40e321060bb..249e6294c22 100755 --- a/libmysql/CMakeLists.txt +++ b/libmysql/CMakeLists.txt @@ -97,7 +97,7 @@ SET(CLIENT_SOURCES ../mysys/array.c ../strings/bchange.c ../strings/bmove.c ../strings/strmov.c ../strings/strnlen.c ../strings/strnmov.c ../strings/strtod.c ../strings/strtoll.c ../strings/strtoull.c ../strings/strxmov.c ../strings/strxnmov.c ../mysys/thr_mutex.c ../mysys/typelib.c ../vio/vio.c ../vio/viosocket.c - ../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c + ../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c ../mysys/mf_qsort.c ../mysys/my_getsystime.c ${LIB_SOURCES}) # Need to set USE_TLS for building the DLL, since __declspec(thread) diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index 02855532e41..53b24c4fb42 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -73,7 +73,7 @@ sqlobjects = net.lo sql_cmn_objects = pack.lo client.lo my_time.lo # Not needed in the minimum library -mysysobjects2 = my_lib.lo +mysysobjects2 = my_lib.lo mf_qsort.lo mysysobjects = $(mysysobjects1) $(mysysobjects2) target_libadd = $(mysysobjects) $(mystringsobjects) $(dbugobjects) \ $(sql_cmn_objects) $(vio_objects) $(sqlobjects) diff --git a/mysql-test/include/mix1.inc b/mysql-test/include/mix1.inc index 7998baa6ccf..e695e7d5570 100644 --- a/mysql-test/include/mix1.inc +++ b/mysql-test/include/mix1.inc @@ -1069,6 +1069,15 @@ DROP TABLE t1; ########################################################################### +# +# Bug #31137: Assertion failed: primary_key_no == -1 || primary_key_no == 0 +# +create table t1(a char(10) not null, unique key aa(a(1)), + b char(4) not null, unique key bb(b(4))) engine=innodb; +desc t1; +show create table t1; +drop table t1; + --echo End of 5.0 tests # Fix for BUG#19243 "wrong LAST_INSERT_ID() after ON DUPLICATE KEY @@ -1353,4 +1362,12 @@ if ($test_foreign_keys) DROP TABLE t1; } +# +# Bug #26447: "ALTER TABLE .. ORDER" does not work with InnoDB and +# auto_increment keys +# +create table t1 (a int auto_increment primary key) engine=innodb; +alter table t1 order by a; +drop table t1; + --echo End of 5.1 tests diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index 4ef247af3a0..0d705104303 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -33,16 +33,14 @@ my $skip_test; sub init_pattern { my ($from, $what)= @_; - if ( $from =~ /[a-z0-9]/ ) { + if ( $from =~ /^[a-z0-9]$/ ) { # Does not contain any regex, make the pattern match # beginning of string $from= "^$from"; } - else { - # Check that pattern is a valid regex - eval { "" =~/$from/; 1 } or - mtr_error("Invalid regex '$from' passed to $what\nPerl says: $@"); - } + # Check that pattern is a valid regex + eval { "" =~/$from/; 1 } or + mtr_error("Invalid regex '$from' passed to $what\nPerl says: $@"); return $from; } diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 150247a427a..7cd65b96c08 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -257,13 +257,13 @@ our $opt_timer= 1; our $opt_user; -our $opt_valgrind= 0; -our $opt_valgrind_mysqld= 0; -our $opt_valgrind_mysqltest= 0; -our $default_valgrind_options= "--show-reachable=yes"; -our $opt_valgrind_options; -our $opt_valgrind_path; -our $opt_callgrind; +my $opt_valgrind= 0; +my $opt_valgrind_mysqld= 0; +my $opt_valgrind_mysqltest= 0; +my @default_valgrind_args= ("--show-reachable=yes"); +my @valgrind_args; +my $opt_valgrind_path; +my $opt_callgrind; our $opt_stress= ""; our $opt_stress_suite= "main"; @@ -577,7 +577,18 @@ sub command_line_setup () { 'valgrind|valgrind-all' => \$opt_valgrind, 'valgrind-mysqltest' => \$opt_valgrind_mysqltest, 'valgrind-mysqld' => \$opt_valgrind_mysqld, - 'valgrind-options=s' => \$opt_valgrind_options, + 'valgrind-options=s' => sub { + my ($opt, $value)= @_; + # Deprecated option unless it's what we know pushbuild uses + if ($value eq "--gen-suppressions=all --show-reachable=yes") { + push(@valgrind_args, $_) for (split(' ', $value)); + return; + } + die("--valgrind-options=s is deprecated. Use ", + "--valgrind-option=s, to be specified several", + " times if necessary"); + }, + 'valgrind-option=s' => \@valgrind_args, 'valgrind-path=s' => \$opt_valgrind_path, 'callgrind' => \$opt_callgrind, @@ -980,7 +991,7 @@ sub command_line_setup () { # -------------------------------------------------------------------------- # Check valgrind arguments # -------------------------------------------------------------------------- - if ( $opt_valgrind or $opt_valgrind_path or defined $opt_valgrind_options) + if ( $opt_valgrind or $opt_valgrind_path or @valgrind_args) { mtr_report("Turning on valgrind for all executables"); $opt_valgrind= 1; @@ -1005,17 +1016,18 @@ sub command_line_setup () { $opt_valgrind_mysqld= 1; # Set special valgrind options unless options passed on command line - $opt_valgrind_options="--trace-children=yes" - unless defined $opt_valgrind_options; + push(@valgrind_args, "--trace-children=yes") + unless @valgrind_args; } if ( $opt_valgrind ) { # Set valgrind_options to default unless already defined - $opt_valgrind_options=$default_valgrind_options - unless defined $opt_valgrind_options; + push(@valgrind_args, @default_valgrind_args) + unless @valgrind_args; - mtr_report("Running valgrind with options \"$opt_valgrind_options\""); + mtr_report("Running valgrind with options \"", + join(" ", @valgrind_args), "\""); } if ( ! $opt_testcase_timeout ) @@ -3770,6 +3782,7 @@ sub mysqld_arguments ($$$$) { # see BUG#28359 mtr_add_arg($args, "%s--connect-timeout=60", $prefix); + # When mysqld is run by a root user(euid is 0), it will fail # to start unless we specify what user to run as. If not running # as root it will be ignored, see BUG#30630 @@ -5075,7 +5088,7 @@ sub valgrind_arguments { } # Add valgrind options, can be overriden by user - mtr_add_arg($args, '%s', $opt_valgrind_options); + mtr_add_arg($args, '%s', $_) for (@valgrind_args); mtr_add_arg($args, $$exe); @@ -5219,12 +5232,14 @@ Options for coverage, profiling etc gcov FIXME gprof FIXME valgrind Run the "mysqltest" and "mysqld" executables using - valgrind with options($default_valgrind_options) + valgrind with default options valgrind-all Synonym for --valgrind valgrind-mysqltest Run the "mysqltest" and "mysql_client_test" executable with valgrind valgrind-mysqld Run the "mysqld" executable with valgrind - valgrind-options=ARGS Options to give valgrind, replaces default options + valgrind-options=ARGS Deprecated, use --valgrind-option + valgrind-option=ARGS Option to give valgrind, replaces default option(s), + can be specified more then once valgrind-path=[EXE] Path to the valgrind executable callgrind Instruct valgrind to use callgrind diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result index 9ee64ee6dbd..d408a0b6153 100644 --- a/mysql-test/r/case.result +++ b/mysql-test/r/case.result @@ -1,4 +1,4 @@ -drop table if exists t1,t2; +drop table if exists t1, t2; select CASE "b" when "a" then 1 when "b" then 2 END; CASE "b" when "a" then 1 when "b" then 2 END 2 @@ -200,3 +200,21 @@ CEMPNUM EMPMUM1 EMPNUM2 0.00 0 0.00 2.00 2 NULL DROP TABLE t1,t2; +End of 4.1 tests +create table t1 (a int, b bigint unsigned); +create table t2 (c int); +insert into t1 (a, b) values (1,4572794622775114594), (2,18196094287899841997), +(3,11120436154190595086); +insert into t2 (c) values (1), (2), (3); +select t1.a, (case t1.a when 0 then 0 else t1.b end) d from t1 +join t2 on t1.a=t2.c order by d; +a d +1 4572794622775114594 +3 11120436154190595086 +2 18196094287899841997 +select t1.a, (case t1.a when 0 then 0 else t1.b end) d from t1 +join t2 on t1.a=t2.c where b=11120436154190595086 order by d; +a d +3 11120436154190595086 +drop table t1, t2; +End of 5.0 tests diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 73a9dba4e69..23d2013cba5 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -763,6 +763,44 @@ t2 CREATE TABLE `t2` ( drop table t1, t2; create table t1(a set("a,b","c,d") not null); ERROR 22007: Illegal set 'a,b' value found during parsing +create database mysqltest; +use mysqltest; +grant create on mysqltest.* to mysqltest@localhost; +create table t1 (i INT); +insert into t1 values (1); +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't1' +create table t2 (i INT); +create table t4 (i INT); +grant select, insert on mysqltest.t2 to mysqltest@localhost; +grant insert on mysqltest.t4 to mysqltest@localhost; +grant create, insert on mysqltest.t5 to mysqltest@localhost; +grant create, insert on mysqltest.t6 to mysqltest@localhost; +flush privileges; +insert into t2 values (1); +create table if not exists t1 select * from t2; +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't1' +create table if not exists t3 select * from t2; +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't3' +create table if not exists t4 select * from t2; +Warnings: +Note 1050 Table 't4' already exists +create table if not exists t5 select * from t2; +create table t6 select * from t2; +create table t7 select * from t2; +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't7' +create table t4 select * from t2; +ERROR 42S01: Table 't4' already exists +create table t1 select * from t2; +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't1' +drop table t1,t2,t4,t5,t6; +revoke create on mysqltest.* from mysqltest@localhost; +revoke select, insert on mysqltest.t2 from mysqltest@localhost; +revoke insert on mysqltest.t4 from mysqltest@localhost; +revoke create, insert on mysqltest.t5 from mysqltest@localhost; +revoke create, insert on mysqltest.t6 from mysqltest@localhost; +flush privileges; +drop database mysqltest; +use test; create table t1 (i int) engine=myisam max_rows=100000000000; show create table t1; Table Create Table diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 991c3bb82de..bd76f2a859f 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -811,6 +811,14 @@ quote(name) ???????? ???????????????? drop table bug20536; +set names ucs2; +ERROR 42000: Variable 'character_set_client' can't be set to the value of 'ucs2' +set names ucs2 collate ucs2_bin; +ERROR 42000: Variable 'character_set_client' can't be set to the value of 'ucs2' +set character_set_client= ucs2; +ERROR 42000: Variable 'character_set_client' can't be set to the value of 'ucs2' +set character_set_client= concat('ucs', substr('2', 1)); +ERROR 42000: Variable 'character_set_client' can't be set to the value of 'ucs2' CREATE TABLE t1(a TEXT CHARSET ucs2 COLLATE ucs2_unicode_ci); INSERT INTO t1 VALUES('abcd'); SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abcd' IN BOOLEAN MODE); diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index aa75cde0525..a7119090ec0 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -212,6 +212,12 @@ test SELECT NAME_CONST('test', 'test'); test test +create table t1 (a int not null); +insert into t1 values (-1), (-2); +select min(a) from t1 group by inet_ntoa(a); +min(a) +-2 +drop table t1; End of 5.0 tests select connection_id() > 0; connection_id() > 0 diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 4379959b60d..c04ec77846a 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -925,7 +925,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL b 4 NULL # Using index explain select a,b from t1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index NULL b 4 NULL # Using index +1 SIMPLE t1 index NULL PRIMARY 4 NULL # explain select a,b,c from t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL # @@ -1153,14 +1153,14 @@ UPDATE t1 set a=a+100 where b between 2 and 3 and a < 1000; SELECT * from t1; a b 1 1 -102 2 -103 3 4 4 5 5 6 6 7 7 8 8 9 9 +102 2 +103 3 drop table t1; CREATE TABLE t1 (a int not null primary key, b int not null, key (b)) engine=innodb; CREATE TABLE t2 (a int not null primary key, b int not null, key (b)) engine=innodb; @@ -1184,7 +1184,6 @@ a b update t1,t2 set t1.a=t1.a+100 where t1.a=101; select * from t1; a b -201 1 102 2 103 3 104 4 @@ -1196,10 +1195,11 @@ a b 110 10 111 11 112 12 +201 1 update t1,t2 set t1.b=t1.b+10 where t1.b=2; select * from t1; a b -201 1 +102 12 103 3 104 4 105 5 @@ -1209,34 +1209,34 @@ a b 109 9 110 10 111 11 -102 12 112 12 +201 1 update t1,t2 set t1.b=t1.b+2,t2.b=t1.b+10 where t1.b between 3 and 5 and t1.a=t2.a+100; select * from t1; a b -201 1 +102 12 103 5 104 6 -106 6 105 7 +106 6 107 7 108 8 109 9 110 10 111 11 -102 12 112 12 +201 1 select * from t2; a b 1 1 2 2 +3 13 +4 14 +5 15 6 6 7 7 8 8 9 9 -3 13 -4 14 -5 15 drop table t1,t2; CREATE TABLE t2 ( NEXT_T BIGINT NOT NULL PRIMARY KEY) ENGINE=MyISAM; CREATE TABLE t1 ( B_ID INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; @@ -1287,11 +1287,11 @@ insert into t1 (id) values (null),(null),(null),(null),(null); update t1 set fk=69 where fk is null order by id limit 1; SELECT * from t1; id fk +1 69 2 NULL 3 NULL 4 NULL 5 NULL -1 69 drop table t1; create table t1 (a int not null, b int not null, key (a)); insert into t1 values (1,1),(1,2),(1,3),(3,1),(3,2),(3,3),(3,1),(3,2),(3,3),(2,1),(2,2),(2,3); @@ -2420,8 +2420,8 @@ insert into t1 (b) values (1); replace into t1 (b) values (2), (1), (3); select * from t1; a b -3 1 2 2 +3 1 4 3 truncate table t1; insert into t1 (b) values (1); @@ -2430,8 +2430,8 @@ replace into t1 (b) values (1); replace into t1 (b) values (3); select * from t1; a b -3 1 2 2 +3 1 4 3 drop table t1; create table t1 (rowid int not null auto_increment, val int not null,primary diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 75bca880305..c3896e97165 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -353,13 +353,13 @@ EXPLAIN SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id WHERE t1.name LIKE 'A%'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index PRIMARY,name name 23 NULL 3 Using where; Using index +1 SIMPLE t1 index PRIMARY,name PRIMARY 4 NULL 3 Using where 1 SIMPLE t2 ref fkey fkey 5 test.t1.id 1 Using where; Using index EXPLAIN SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id WHERE t1.name LIKE 'A%' OR FALSE; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 index NULL fkey 5 NULL 5 Using index +1 SIMPLE t2 index NULL PRIMARY 4 NULL 5 1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.fkey 1 Using where DROP TABLE t1,t2; CREATE TABLE t1 ( @@ -1264,11 +1264,11 @@ select_type SIMPLE table t1 type index possible_keys NULL -key b -key_len 5 +key PRIMARY +key_len 4 ref NULL rows 3 -Extra Using index; Using filesort +Extra Using filesort SELECT * FROM t1 ORDER BY b ASC, a DESC; a b 1 1 @@ -1280,11 +1280,11 @@ select_type SIMPLE table t1 type index possible_keys NULL -key b -key_len 5 +key PRIMARY +key_len 4 ref NULL rows 3 -Extra Using index; Using filesort +Extra Using filesort SELECT * FROM t1 ORDER BY b DESC, a ASC; a b 2 2 @@ -1325,6 +1325,21 @@ test t1 Redundant # - that's it, cleanup. DROP TABLE t1; +create table t1(a char(10) not null, unique key aa(a(1)), +b char(4) not null, unique key bb(b(4))) engine=innodb; +desc t1; +Field Type Null Key Default Extra +a char(10) NO UNI NULL +b char(4) NO PRI NULL +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(10) NOT NULL, + `b` char(4) NOT NULL, + UNIQUE KEY `bb` (`b`), + UNIQUE KEY `aa` (`a`(1)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +drop table t1; End of 5.0 tests CREATE TABLE `t2` ( `k` int(11) NOT NULL auto_increment, @@ -1573,4 +1588,9 @@ t2 CREATE TABLE `t2` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 DROP TABLE t2; DROP TABLE t1; +create table t1 (a int auto_increment primary key) engine=innodb; +alter table t1 order by a; +Warnings: +Warning 1105 ORDER BY ignored as there is a user-defined clustered index in the table 't1' +drop table t1; End of 5.1 tests diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result index 8dbba4d454a..919aff4bfb7 100644 --- a/mysql-test/r/insert.result +++ b/mysql-test/r/insert.result @@ -499,4 +499,138 @@ i 2 2 DROP TABLE t1, t2; +CREATE TABLE t1 ( +a char(20) NOT NULL, +b char(7) DEFAULT NULL, +c char(4) DEFAULT NULL +); +INSERT INTO t1(a,b,c) VALUES (9.999999e+0, 9.999999e+0, 9.999e+0); +INSERT INTO t1(a,b,c) VALUES (1.225e-05, 1.225e-05, 1.225e-05); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +INSERT INTO t1(a,b) VALUES (1.225e-04, 1.225e-04); +INSERT INTO t1(a,b) VALUES (1.225e-01, 1.225e-01); +INSERT INTO t1(a,b) VALUES (1.225877e-01, 1.225877e-01); +INSERT INTO t1(a,b) VALUES (1.225e+01, 1.225e+01); +INSERT INTO t1(a,b,c) VALUES (1.225e+01, 1.225e+01, 1.225e+01); +INSERT INTO t1(a,b) VALUES (1.225e+05, 1.225e+05); +INSERT INTO t1(a,b) VALUES (1.225e+10, 1.225e+10); +INSERT INTO t1(a,b) VALUES (1.225e+15, 1.225e+15); +INSERT INTO t1(a,b) VALUES (5000000e+0, 5000000e+0); +INSERT INTO t1(a,b) VALUES (1.25e+78, 1.25e+78); +INSERT INTO t1(a,b) VALUES (1.25e-94, 1.25e-94); +INSERT INTO t1(a,b) VALUES (1.25e+203, 1.25e+203); +INSERT INTO t1(a,b) VALUES (1.25e-175, 1.25e-175); +INSERT INTO t1(a,c) VALUES (1.225e+0, 1.225e+0); +INSERT INTO t1(a,c) VALUES (1.37e+0, 1.37e+0); +INSERT INTO t1(a,c) VALUES (-1.37e+0, -1.37e+0); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +INSERT INTO t1(a,c) VALUES (1.87e-3, 1.87e-3); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +INSERT INTO t1(a,c) VALUES (-1.87e-2, -1.87e-2); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +INSERT INTO t1(a,c) VALUES (5000e+0, 5000e+0); +INSERT INTO t1(a,c) VALUES (-5000e+0, -5000e+0); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +SELECT * FROM t1; +a b c +9.999999 10 10 +1.225e-05 1.2e-05 1e-0 +0.0001225 0.00012 NULL +0.1225 0.1225 NULL +0.1225877 0.12259 NULL +12.25 12.25 NULL +12.25 12.25 12.2 +122500 122500 NULL +12250000000 1.2e+10 NULL +1.225e+15 1.2e+15 NULL +5000000 5000000 NULL +1.25e+78 1.2e+78 NULL +1.25e-94 1.2e-94 NULL +1.25e+203 1e+203 NULL +1.25e-175 1e-175 NULL +1.225 NULL 1.23 +1.37 NULL 1.37 +-1.37 NULL -1.3 +0.00187 NULL 0.00 +-0.0187 NULL -0.0 +5000 NULL 5000 +-5000 NULL -500 +DROP TABLE t1; +CREATE TABLE t1 ( +a char(20) NOT NULL, +b char(7) DEFAULT NULL, +c char(5) +); +INSERT INTO t1(a,b,c) VALUES (9.999999e+0, 9.999999e+0, 9.999e+0); +INSERT INTO t1(a,b,c) VALUES (1.225e-05, 1.225e-05, 1.225e-05); +INSERT INTO t1(a,b) VALUES (1.225e-04, 1.225e-04); +INSERT INTO t1(a,b) VALUES (1.225e-01, 1.225e-01); +INSERT INTO t1(a,b) VALUES (1.225877e-01, 1.225877e-01); +INSERT INTO t1(a,b) VALUES (1.225e+01, 1.225e+01); +INSERT INTO t1(a,b,c) VALUES (1.225e+01, 1.225e+01, 1.225e+01); +INSERT INTO t1(a,b) VALUES (1.225e+05, 1.225e+05); +INSERT INTO t1(a,b) VALUES (1.225e+10, 1.225e+10); +INSERT INTO t1(a,b) VALUES (1.225e+15, 1.225e+15); +INSERT INTO t1(a,b) VALUES (5000000e+0, 5000000e+0); +INSERT INTO t1(a,b) VALUES (1.25e+78, 1.25e+78); +INSERT INTO t1(a,b) VALUES (1.25e-94, 1.25e-94); +INSERT INTO t1(a,b) VALUES (1.25e+203, 1.25e+203); +INSERT INTO t1(a,b) VALUES (1.25e-175, 1.25e-175); +INSERT INTO t1(a,c) VALUES (1.225e+0, 1.225e+0); +INSERT INTO t1(a,c) VALUES (1.37e+0, 1.37e+0); +INSERT INTO t1(a,c) VALUES (-1.37e+0, -1.37e+0); +INSERT INTO t1(a,c) VALUES (1.87e-3, 1.87e-3); +INSERT INTO t1(a,c) VALUES (-1.87e-2, -1.87e-2); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +INSERT INTO t1(a,c) VALUES (5000e+0, 5000e+0); +INSERT INTO t1(a,c) VALUES (-5000e+0, -5000e+0); +SELECT * FROM t1; +a b c +9.999999 10 9.999 +1.225e-05 1.2e-05 1e-05 +0.0001225 0.00012 NULL +0.1225 0.1225 NULL +0.1225877 0.12259 NULL +12.25 12.25 NULL +12.25 12.25 12.25 +122500 122500 NULL +12250000000 1.2e+10 NULL +1.225e+15 1.2e+15 NULL +5000000 5000000 NULL +1.25e+78 1.2e+78 NULL +1.25e-94 1.2e-94 NULL +1.25e+203 1e+203 NULL +1.25e-175 1e-175 NULL +1.225 NULL 1.225 +1.37 NULL 1.37 +-1.37 NULL -1.37 +0.00187 NULL 0.002 +-0.0187 NULL -0.01 +5000 NULL 5000 +-5000 NULL -5000 +DROP TABLE t1; +CREATE TABLE t (a CHAR(10),b INT); +INSERT INTO t VALUES (),(),(); +INSERT INTO t(a) SELECT rand() FROM t; +DROP TABLE t; +CREATE TABLE t1 (c1 INT NOT NULL); +INSERT INTO t1 VALUES(4188.32999999999992724042385816574096679687500), +('4188.32999999999992724042385816574096679687500'), (4188); +SELECT * FROM t1; +c1 +4188 +4188 +4188 +CREATE TABLE t2 (c1 BIGINT); +INSERT INTO t2 VALUES('15449237462.0000000000'); +SELECT * FROM t2; +c1 +15449237462 +DROP TABLE t1, t2; End of 5.0 tests. diff --git a/mysql-test/r/join_outer_innodb.result b/mysql-test/r/join_outer_innodb.result index e8a2d6f668b..24a11b12b03 100644 --- a/mysql-test/r/join_outer_innodb.result +++ b/mysql-test/r/join_outer_innodb.result @@ -8,12 +8,12 @@ EXPLAIN SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id WHERE t1.name LIKE 'A%'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index PRIMARY,name name 23 NULL 3 Using where; Using index +1 SIMPLE t1 index PRIMARY,name PRIMARY 4 NULL 3 Using where 1 SIMPLE t2 ref fkey fkey 5 test.t1.id 1 Using where; Using index EXPLAIN SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id WHERE t1.name LIKE 'A%' OR FALSE; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 index NULL fkey 5 NULL 5 Using index +1 SIMPLE t2 index NULL PRIMARY 4 NULL 5 1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.fkey 1 Using where DROP TABLE t1,t2; diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result index 3db5e926d30..fcc09a0244d 100644 --- a/mysql-test/r/key.result +++ b/mysql-test/r/key.result @@ -530,6 +530,51 @@ ORDER BY c.b, c.d a b c d e f g h i j a b c d 2 2 1 2004-11-30 12:00:00 1 0 0 0 0 0 2 3388000 -553000 NULL DROP TABLE t1, t2; +create table t1(a int not null, key aa(a), +b char(10) not null, unique key bb(b(1)), +c char(4) not null, unique key cc(c)); +desc t1; +Field Type Null Key Default Extra +a int(11) NO MUL NULL +b char(10) NO UNI NULL +c char(4) NO PRI NULL +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` char(10) NOT NULL, + `c` char(4) NOT NULL, + UNIQUE KEY `cc` (`c`), + UNIQUE KEY `bb` (`b`(1)), + KEY `aa` (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +create table t1(a int not null, key aa(a), +b char(10) not null, unique key bb(b(1)), +c char(4) not null); +desc t1; +Field Type Null Key Default Extra +a int(11) NO MUL NULL +b char(10) NO UNI NULL +c char(4) NO NULL +alter table t1 add unique key cc(c); +desc t1; +Field Type Null Key Default Extra +a int(11) NO MUL NULL +b char(10) NO UNI NULL +c char(4) NO PRI NULL +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` char(10) NOT NULL, + `c` char(4) NOT NULL, + UNIQUE KEY `cc` (`c`), + UNIQUE KEY `bb` (`b`(1)), + KEY `aa` (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +End of 5.0 tests DROP TABLE IF EXISTS t1; CREATE TABLE t1 (a INT PRIMARY KEY AUTO_INCREMENT); INSERT INTO t1 VALUES (), (), (); diff --git a/mysql-test/r/log_state.result b/mysql-test/r/log_state.result index b0ec0d25935..8ecfe3b2094 100644 --- a/mysql-test/r/log_state.result +++ b/mysql-test/r/log_state.result @@ -237,4 +237,16 @@ SELECT @@slow_query_log, @@log_slow_queries; 1 1 SET GLOBAL general_log = @old_general_log_state; SET GLOBAL slow_query_log = @old_slow_log_state; +set @old_general_log_file= @@global.general_log_file; +set @old_slow_query_log_file= @@global.slow_query_log_file; +set global general_log_file= concat('/not exiting path/log.maste', 'r'); +ERROR 42000: Variable 'general_log_file' can't be set to the value of '/not exiting path/log.master' +set global general_log_file= NULL; +ERROR 42000: Variable 'general_log_file' can't be set to the value of 'NULL' +set global slow_query_log_file= concat('/not exiting path/log.maste', 'r'); +ERROR 42000: Variable 'slow_query_log_file' can't be set to the value of '/not exiting path/log.master' +set global slow_query_log_file= NULL; +ERROR 42000: Variable 'slow_query_log_file' can't be set to the value of 'NULL' +set global general_log_file= @old_general_log_file; +set global slow_query_log_file= @old_slow_query_log_file; End of 5.1 tests diff --git a/mysql-test/r/mysqlcheck.result b/mysql-test/r/mysqlcheck.result index b8ada0adff9..047b2662b1b 100644 --- a/mysql-test/r/mysqlcheck.result +++ b/mysql-test/r/mysqlcheck.result @@ -1,4 +1,4 @@ -DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t1, `t``1`, `t 1`; drop view if exists v1; drop database if exists client_test_db; mysql.columns_priv OK @@ -57,4 +57,27 @@ test.t1 OK test.t1 OK drop view v1; drop table t1; +create table `t``1`(a int); +create table `t 1`(a int); +test.t 1 OK +test.t`1 OK +drop table `t``1`, `t 1`; End of 5.0 tests +create table t1(a int); +create view v1 as select * from t1; +show tables; +Tables_in_test +t1 +v1 +show tables; +Tables_in_test +t1 +#mysql50#v-1 +v1 +show tables; +Tables_in_test +t1 +v1 +v-1 +drop view v1, `v-1`; +drop table t1; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 9d0906ad5e7..ae68f8a4c5e 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1143,6 +1143,11 @@ a 13 DEALLOCATE PREPARE st1; DROP TABLE t1; +create table t1 (a int, b tinyint); +prepare st1 from 'update t1 set b= (str_to_date(a, a))'; +execute st1; +deallocate prepare st1; +drop table t1; End of 4.1 tests. create table t1 (a varchar(20)); insert into t1 values ('foo'); diff --git a/mysql-test/r/status.result b/mysql-test/r/status.result index db75044ee5d..c95b09597fc 100644 --- a/mysql-test/r/status.result +++ b/mysql-test/r/status.result @@ -8,6 +8,8 @@ VARIABLE_NAME VARIABLE_VALUE TABLE_LOCKS_IMMEDIATE 2 TABLE_LOCKS_WAITED 0 SET SQL_LOG_BIN=0; +set @old_general_log = @@global.general_log; +set global general_log = 'OFF'; drop table if exists t1; create table t1(n int) engine=myisam; insert into t1 values(1); @@ -20,6 +22,7 @@ show status like 'Table_locks_waited'; Variable_name Value Table_locks_waited 1 drop table t1; +set global general_log = @old_general_log; select 1; 1 1 diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 24be10a7a29..71be41b106f 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -1509,6 +1509,26 @@ SELECT 1 FROM t1 GROUP BY @b := @a, @b; 1 1 DROP TABLE t1; +CREATE TABLE t1 SELECT 0.123456789012345678901234567890123456 AS f1; +Warnings: +Note 1265 Data truncated for column 'f1' at row 1 +DESC t1; +Field Type Null Key Default Extra +f1 decimal(31,30) NO 0.000000000000000000000000000000 +SELECT f1 FROM t1; +f1 +0.123456789012345678901234567890 +DROP TABLE t1; +CREATE TABLE t1 SELECT 123451234512345123451234512345123451234512345.678906789067890678906789067890678906789067890 AS f1; +Warnings: +Warning 1264 Out of range value for column 'f1' at row 1 +DESC t1; +Field Type Null Key Default Extra +f1 decimal(59,30) NO 0.000000000000000000000000000000 +SELECT f1 FROM t1; +f1 +99999999999999999999999999999.999999999999999999999999999999 +DROP TABLE t1; End of 5.0 tests select cast(143.481 as decimal(4,1)); cast(143.481 as decimal(4,1)) diff --git a/mysql-test/suite/rpl/t/rpl_ssl.test b/mysql-test/suite/rpl/t/rpl_ssl.test index be730b35c13..7e256390e25 100644 --- a/mysql-test/suite/rpl/t/rpl_ssl.test +++ b/mysql-test/suite/rpl/t/rpl_ssl.test @@ -81,6 +81,16 @@ if (`select $slave_count != $master_count`) echo master and slave differed in number of rows; echo master: $master_count; echo slave: $slave_count; + + connection master; + echo === master ===; + select count(*) t1; + select * from t1; + connection slave; + echo === slave ===; + select count(*) t1; + select * from t1; + query_vertical show slave status; } connection master; diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test index 63baeebcf12..028c64d6de7 100644 --- a/mysql-test/t/case.test +++ b/mysql-test/t/case.test @@ -1,9 +1,9 @@ -# + # Testing of CASE # --disable_warnings -drop table if exists t1,t2; +drop table if exists t1, t2; --enable_warnings select CASE "b" when "a" then 1 when "b" then 2 END; @@ -152,4 +152,21 @@ SELECT IFNULL(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM, FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM; DROP TABLE t1,t2; -# End of 4.1 tests + +--echo End of 4.1 tests + +# +# #30782: Truncated UNSIGNED BIGINT columns +# +create table t1 (a int, b bigint unsigned); +create table t2 (c int); +insert into t1 (a, b) values (1,4572794622775114594), (2,18196094287899841997), + (3,11120436154190595086); +insert into t2 (c) values (1), (2), (3); +select t1.a, (case t1.a when 0 then 0 else t1.b end) d from t1 + join t2 on t1.a=t2.c order by d; +select t1.a, (case t1.a when 0 then 0 else t1.b end) d from t1 + join t2 on t1.a=t2.c where b=11120436154190595086 order by d; +drop table t1, t2; + +--echo End of 5.0 tests diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 45ee4c1c88d..15c36dfff84 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -658,6 +658,82 @@ drop table t1, t2; --error 1367 create table t1(a set("a,b","c,d") not null); +# +# Bug #20901 - CREATE privilege is enough to insert into a table +# + +create database mysqltest; +use mysqltest; + +grant create on mysqltest.* to mysqltest@localhost; +create table t1 (i INT); + +connect (user1,localhost,mysqltest,,mysqltest); +connection user1; +# show we don't have INSERT +--error 1142 +insert into t1 values (1); +# show we have CREATE +create table t2 (i INT); +create table t4 (i INT); + +connection default; +grant select, insert on mysqltest.t2 to mysqltest@localhost; +grant insert on mysqltest.t4 to mysqltest@localhost; +# to specify ACLs for non-existent objects, must explictly |CREATE +grant create, insert on mysqltest.t5 to mysqltest@localhost; +grant create, insert on mysqltest.t6 to mysqltest@localhost; +flush privileges; + +connection user1; +insert into t2 values (1); + + +# CREATE IF NOT EXISTS...SELECT, t1 exists, no INSERT, must fail +--error 1142 +create table if not exists t1 select * from t2; + +# CREATE IF NOT EXISTS...SELECT, no t3 yet, no INSERT, must fail +--error 1142 +create table if not exists t3 select * from t2; + +# CREATE IF NOT EXISTS...SELECT, t4 exists, have INSERT, must succeed +create table if not exists t4 select * from t2; + +# CREATE IF NOT EXISTS...SELECT, no t5 yet, have INSERT, must succeed +create table if not exists t5 select * from t2; + + +# CREATE...SELECT, no t6 yet, have INSERT, must succeed +create table t6 select * from t2; + +# CREATE...SELECT, no t7 yet, no INSERT, must fail +--error 1142 +create table t7 select * from t2; + +# CREATE...SELECT, t4 exists, have INSERT, must still fail (exists) +--error 1050 +create table t4 select * from t2; + +# CREATE...SELECT, t1 exists, no INSERT, must fail +--error 1142 +create table t1 select * from t2; + + +connection default; +drop table t1,t2,t4,t5,t6; + +revoke create on mysqltest.* from mysqltest@localhost; +revoke select, insert on mysqltest.t2 from mysqltest@localhost; +revoke insert on mysqltest.t4 from mysqltest@localhost; +revoke create, insert on mysqltest.t5 from mysqltest@localhost; +revoke create, insert on mysqltest.t6 from mysqltest@localhost; +flush privileges; + +disconnect user1; +drop database mysqltest; +use test; + # End of 4.1 tests diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index de2033321b9..e5c21bb72a0 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -555,6 +555,18 @@ INSERT INTO t1 VALUES('abcd'); SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abcd' IN BOOLEAN MODE); DROP TABLE t1; +# +# Bug #31615: crash after set names ucs2 collate xxx +# +--error 1231 +set names ucs2; +--error 1231 +set names ucs2 collate ucs2_bin; +--error 1231 +set character_set_client= ucs2; +--error 1231 +set character_set_client= concat('ucs', substr('2', 1)); + --echo End of 4.1 tests # diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index 4b7685c3633..fb85cdfb27d 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -213,6 +213,14 @@ SELECT NAME_CONST('test', 1.0); SELECT NAME_CONST('test', -1.0); SELECT NAME_CONST('test', 'test'); +# +# Bug #31349: ERROR 1062 (23000): Duplicate entry '' for key 'group_key' +# +create table t1 (a int not null); +insert into t1 values (-1), (-2); +select min(a) from t1 group by inet_ntoa(a); +drop table t1; + --echo End of 5.0 tests # diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test index 3d32da9c3b7..c58fb61ad30 100644 --- a/mysql-test/t/insert.test +++ b/mysql-test/t/insert.test @@ -387,5 +387,106 @@ SELECT * FROM t2; DROP TABLE t1, t2; +# +# Bug #26788: mysqld (debug) aborts when inserting specific numbers into char +# fields +# + +CREATE TABLE t1 ( + a char(20) NOT NULL, + b char(7) DEFAULT NULL, + c char(4) DEFAULT NULL +); + +INSERT INTO t1(a,b,c) VALUES (9.999999e+0, 9.999999e+0, 9.999e+0); +INSERT INTO t1(a,b,c) VALUES (1.225e-05, 1.225e-05, 1.225e-05); +INSERT INTO t1(a,b) VALUES (1.225e-04, 1.225e-04); +INSERT INTO t1(a,b) VALUES (1.225e-01, 1.225e-01); +INSERT INTO t1(a,b) VALUES (1.225877e-01, 1.225877e-01); +INSERT INTO t1(a,b) VALUES (1.225e+01, 1.225e+01); +INSERT INTO t1(a,b,c) VALUES (1.225e+01, 1.225e+01, 1.225e+01); +INSERT INTO t1(a,b) VALUES (1.225e+05, 1.225e+05); +INSERT INTO t1(a,b) VALUES (1.225e+10, 1.225e+10); +INSERT INTO t1(a,b) VALUES (1.225e+15, 1.225e+15); +INSERT INTO t1(a,b) VALUES (5000000e+0, 5000000e+0); +INSERT INTO t1(a,b) VALUES (1.25e+78, 1.25e+78); +INSERT INTO t1(a,b) VALUES (1.25e-94, 1.25e-94); +INSERT INTO t1(a,b) VALUES (1.25e+203, 1.25e+203); +INSERT INTO t1(a,b) VALUES (1.25e-175, 1.25e-175); +INSERT INTO t1(a,c) VALUES (1.225e+0, 1.225e+0); +INSERT INTO t1(a,c) VALUES (1.37e+0, 1.37e+0); +INSERT INTO t1(a,c) VALUES (-1.37e+0, -1.37e+0); +INSERT INTO t1(a,c) VALUES (1.87e-3, 1.87e-3); +INSERT INTO t1(a,c) VALUES (-1.87e-2, -1.87e-2); +INSERT INTO t1(a,c) VALUES (5000e+0, 5000e+0); +INSERT INTO t1(a,c) VALUES (-5000e+0, -5000e+0); +# Expected results are "12.2" and "1.2e+78", but Windows returns "12.3" and +# "1.3e+78" due to different rounding rules +--replace_result 12.3 12.2 1.3e+78 1.2e+78 +SELECT * FROM t1; + +DROP TABLE t1; + +CREATE TABLE t1 ( + a char(20) NOT NULL, + b char(7) DEFAULT NULL, + c char(5) +); + + +INSERT INTO t1(a,b,c) VALUES (9.999999e+0, 9.999999e+0, 9.999e+0); +INSERT INTO t1(a,b,c) VALUES (1.225e-05, 1.225e-05, 1.225e-05); +INSERT INTO t1(a,b) VALUES (1.225e-04, 1.225e-04); +INSERT INTO t1(a,b) VALUES (1.225e-01, 1.225e-01); +INSERT INTO t1(a,b) VALUES (1.225877e-01, 1.225877e-01); +INSERT INTO t1(a,b) VALUES (1.225e+01, 1.225e+01); +INSERT INTO t1(a,b,c) VALUES (1.225e+01, 1.225e+01, 1.225e+01); +INSERT INTO t1(a,b) VALUES (1.225e+05, 1.225e+05); +INSERT INTO t1(a,b) VALUES (1.225e+10, 1.225e+10); +INSERT INTO t1(a,b) VALUES (1.225e+15, 1.225e+15); +INSERT INTO t1(a,b) VALUES (5000000e+0, 5000000e+0); +INSERT INTO t1(a,b) VALUES (1.25e+78, 1.25e+78); +INSERT INTO t1(a,b) VALUES (1.25e-94, 1.25e-94); +INSERT INTO t1(a,b) VALUES (1.25e+203, 1.25e+203); +INSERT INTO t1(a,b) VALUES (1.25e-175, 1.25e-175); +INSERT INTO t1(a,c) VALUES (1.225e+0, 1.225e+0); +INSERT INTO t1(a,c) VALUES (1.37e+0, 1.37e+0); +INSERT INTO t1(a,c) VALUES (-1.37e+0, -1.37e+0); +INSERT INTO t1(a,c) VALUES (1.87e-3, 1.87e-3); +INSERT INTO t1(a,c) VALUES (-1.87e-2, -1.87e-2); +INSERT INTO t1(a,c) VALUES (5000e+0, 5000e+0); +INSERT INTO t1(a,c) VALUES (-5000e+0, -5000e+0); + +# Expected results are "12.2" and "1.2e+78", but Windows returns "12.3" and +# "1.3e+78" due to different rounding rules +--replace_result 12.3 12.2 1.3e+78 1.2e+78 +SELECT * FROM t1; + +DROP TABLE t1; + +# +# Bug #31152: assertion in Field_str::store(double) +# + +CREATE TABLE t (a CHAR(10),b INT); +INSERT INTO t VALUES (),(),(); +INSERT INTO t(a) SELECT rand() FROM t; +DROP TABLE t; + +# +# Bug #30453: String not cast to int correctly +# + +CREATE TABLE t1 (c1 INT NOT NULL); +INSERT INTO t1 VALUES(4188.32999999999992724042385816574096679687500), +('4188.32999999999992724042385816574096679687500'), (4188); +SELECT * FROM t1; + +CREATE TABLE t2 (c1 BIGINT); +INSERT INTO t2 VALUES('15449237462.0000000000'); +SELECT * FROM t2; + +DROP TABLE t1, t2; + --echo End of 5.0 tests. diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test index 31d5ac5201b..9a4158d8e13 100644 --- a/mysql-test/t/key.test +++ b/mysql-test/t/key.test @@ -503,6 +503,26 @@ ORDER BY c.b, c.d DROP TABLE t1, t2; # +# Bug #31137: Assertion failed: primary_key_no == -1 || primary_key_no == 0 +# +create table t1(a int not null, key aa(a), + b char(10) not null, unique key bb(b(1)), + c char(4) not null, unique key cc(c)); +desc t1; +show create table t1; +drop table t1; +create table t1(a int not null, key aa(a), + b char(10) not null, unique key bb(b(1)), + c char(4) not null); +desc t1; +alter table t1 add unique key cc(c); +desc t1; +show create table t1; +drop table t1; + +--echo End of 5.0 tests + +# # Bug #31148: bool close_thread_table(THD*, TABLE**): Assertion # `table->key_read == 0' failed. # diff --git a/mysql-test/t/log_state.test b/mysql-test/t/log_state.test index f7795e49b37..a340238b724 100644 --- a/mysql-test/t/log_state.test +++ b/mysql-test/t/log_state.test @@ -213,6 +213,24 @@ SELECT @@slow_query_log, @@log_slow_queries; SET GLOBAL general_log = @old_general_log_state; SET GLOBAL slow_query_log = @old_slow_log_state; +# +# Bug #31604: server crash when setting slow_query_log_file/general_log_file +# +set @old_general_log_file= @@global.general_log_file; +set @old_slow_query_log_file= @@global.slow_query_log_file; + +--error 1231 +set global general_log_file= concat('/not exiting path/log.maste', 'r'); +--error 1231 +set global general_log_file= NULL; +--error 1231 +set global slow_query_log_file= concat('/not exiting path/log.maste', 'r'); +--error 1231 +set global slow_query_log_file= NULL; + +set global general_log_file= @old_general_log_file; +set global slow_query_log_file= @old_slow_query_log_file; + --echo End of 5.1 tests --enable_ps_protocol diff --git a/mysql-test/t/mysqlcheck.test b/mysql-test/t/mysqlcheck.test index d233546f9e3..6a7f44b4dbe 100644 --- a/mysql-test/t/mysqlcheck.test +++ b/mysql-test/t/mysqlcheck.test @@ -11,7 +11,7 @@ # --disable_warnings -DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t1, `t``1`, `t 1`; drop view if exists v1; drop database if exists client_test_db; --enable_warnings @@ -37,4 +37,26 @@ create view v1 as select * from t1; drop view v1; drop table t1; +# +# Bug #30654: mysqlcheck fails during upgrade of tables whose names include backticks +# +create table `t``1`(a int); +create table `t 1`(a int); +--replace_result 'Table is already up to date' OK +--exec $MYSQL_CHECK --databases test +drop table `t``1`, `t 1`; + --echo End of 5.0 tests + +# +# Bug #30679: 5.1 name encoding not performed for views during upgrade +# +create table t1(a int); +create view v1 as select * from t1; +show tables; +--copy_file $MYSQLTEST_VARDIR/master-data/test/v1.frm $MYSQLTEST_VARDIR/master-data/test/v-1.frm +show tables; +--exec $MYSQL_CHECK --check-upgrade --fix-table-names --databases test +show tables; +drop view v1, `v-1`; +drop table t1; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index fd7caeb195e..b45d67d8485 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1223,6 +1223,16 @@ EXECUTE st1; DEALLOCATE PREPARE st1; DROP TABLE t1; + +# +# Bug #32137: prepared statement crash with str_to_date in update clause +# +create table t1 (a int, b tinyint); +prepare st1 from 'update t1 set b= (str_to_date(a, a))'; +execute st1; +deallocate prepare st1; +drop table t1; + --echo End of 4.1 tests. ############################# 5.0 tests start ################################ diff --git a/mysql-test/t/status.test b/mysql-test/t/status.test index 1cd5aa1726a..6a11791924a 100644 --- a/mysql-test/t/status.test +++ b/mysql-test/t/status.test @@ -21,6 +21,8 @@ select * from information_schema.session_status where variable_name like 'Table_ connection con1; # ++Immediate = 3 SET SQL_LOG_BIN=0; +set @old_general_log = @@global.general_log; +set global general_log = 'OFF'; --disable_warnings # ++Immediate = 4 drop table if exists t1; @@ -60,6 +62,7 @@ reap; # ++Immediate = 16 + $wait_condition_reps show status like 'Table_locks_waited'; drop table t1; +set global general_log = @old_general_log; disconnect con2; disconnect con1; diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index ed3abb12140..9aa8c00d24a 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -116,15 +116,10 @@ drop table if exists t1; # Check conversion of floats to character field (Bug #7774) create table t1 (c char(20)); insert into t1 values (5e-28); -# Expected result is "5e-28", but windows returns "5e-028" ---replace_result 5e-028 5e-28 select * from t1; drop table t1; create table t1 (c char(6)); insert into t1 values (2e5),(2e6),(2e-4),(2e-5); -# Expected result is "2e+06", but windows returns "2e+006" -# Expected result is "2e-05", but windows returns "2e-005" ---replace_result 2e+006 2e+06 2e-005 2e-05 select * from t1; drop table t1; diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index b1776d09744..4b052a3d1fb 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -1205,6 +1205,27 @@ SELECT 1 FROM t1 GROUP BY @b := @a, @b; DROP TABLE t1; +# +# Bug #24907: unpredictable (display) precission, if input precission +# increases +# + +# As per 10.1.1. Overview of Numeric Types, type (new) DECIMAL has a +# maxmimum precision of 30 places after the decimal point. Show that +# temp field creation beyond that works and throws a truncation warning. +# DECIMAL(37,36) should be adjusted to DECIMAL(31,30). +CREATE TABLE t1 SELECT 0.123456789012345678901234567890123456 AS f1; +DESC t1; +SELECT f1 FROM t1; +DROP TABLE t1; + +# too many decimal places, AND too many digits altogether (90 = 45+45). +# should preserve integers (65 = 45+20) +CREATE TABLE t1 SELECT 123451234512345123451234512345123451234512345.678906789067890678906789067890678906789067890 AS f1; +DESC t1; +SELECT f1 FROM t1; +DROP TABLE t1; + --echo End of 5.0 tests # diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index c81da9a469a..a03d71f32d8 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -3429,7 +3429,7 @@ static int flush_cached_blocks(KEY_CACHE *keycache, As all blocks referred in 'cache' are marked by BLOCK_IN_FLUSH we are guarunteed no thread will change them */ - qsort((uchar*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link); + my_qsort((uchar*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link); keycache_pthread_mutex_lock(&keycache->cache_lock); /* diff --git a/mysys/mf_qsort.c b/mysys/mf_qsort.c index 3d52d56c952..4b3ecb603a6 100644 --- a/mysys/mf_qsort.c +++ b/mysys/mf_qsort.c @@ -91,10 +91,10 @@ typedef struct st_stack *****************************************************************************/ #ifdef QSORT_EXTRA_CMP_ARGUMENT -qsort_t qsort2(void *base_ptr, size_t count, size_t size, qsort2_cmp cmp, +qsort_t my_qsort2(void *base_ptr, size_t count, size_t size, qsort2_cmp cmp, void *cmp_argument) #else -qsort_t qsort(void *base_ptr, size_t count, size_t size, qsort_cmp cmp) +qsort_t my_qsort(void *base_ptr, size_t count, size_t size, qsort_cmp cmp) #endif { char *low, *high, *pivot; diff --git a/mysys/mf_sort.c b/mysys/mf_sort.c index 741c8f42327..686ebbc1d14 100644 --- a/mysys/mf_sort.c +++ b/mysys/mf_sort.c @@ -34,8 +34,8 @@ void my_string_ptr_sort(uchar *base, uint items, size_t size) { if (size && items) { - qsort2(base,items, sizeof(uchar*), get_ptr_compare(size), - (void*) &size); + my_qsort2(base,items, sizeof(uchar*), get_ptr_compare(size), + (void*) &size); } } } diff --git a/mysys/my_lib.c b/mysys/my_lib.c index c10b2e391b4..c18d14fb549 100644 --- a/mysys/my_lib.c +++ b/mysys/my_lib.c @@ -180,7 +180,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) result->number_off_files= dir_entries_storage->elements; if (!(MyFlags & MY_DONT_SORT)) - qsort((void *) result->dir_entry, result->number_off_files, + my_qsort((void *) result->dir_entry, result->number_off_files, sizeof(FILEINFO), (qsort_cmp) comp_names); DBUG_RETURN(result); @@ -491,7 +491,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) result->number_off_files= dir_entries_storage->elements; if (!(MyFlags & MY_DONT_SORT)) - qsort((void *) result->dir_entry, result->number_off_files, + my_qsort((void *) result->dir_entry, result->number_off_files, sizeof(FILEINFO), (qsort_cmp) comp_names); DBUG_PRINT("exit", ("found %d files", result->number_off_files)); DBUG_RETURN(result); diff --git a/mysys/my_write.c b/mysys/my_write.c index 056a84f1794..c67b1d8f3f2 100644 --- a/mysys/my_write.c +++ b/mysys/my_write.c @@ -29,6 +29,10 @@ size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags) Filedes, (long) Buffer, (ulong) Count, MyFlags)); errors=0; written=0; + /* The behavior of write(fd, buf, 0) is not portable */ + if (unlikely(!Count)) + DBUG_RETURN(0); + for (;;) { if ((writenbytes= write(Filedes, Buffer, Count)) == Count) diff --git a/mysys/queues.c b/mysys/queues.c index d8a7ca19bee..bc7f0b74b4f 100644 --- a/mysys/queues.c +++ b/mysys/queues.c @@ -382,7 +382,7 @@ void queue_fix(QUEUE *queue) make test_priority_queue ./test_priority_queue - Written by Mikael Ronström, 2005 + Written by Mikael Ronström, 2005 */ static uint num_array[1025]; diff --git a/sql/field.cc b/sql/field.cc index cd8228305e4..942c0538abb 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -6401,24 +6401,74 @@ int Field_str::store(double nr) ASSERT_COLUMN_MARKED_FOR_WRITE; char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE]; uint length; - bool use_scientific_notation= TRUE; uint local_char_length= field_length / charset()->mbmaxlen; - /* - Check fabs(nr) against longest value that can be stored in field, - which depends on whether the value is < 1 or not, and negative or not - */ double anr= fabs(nr); + bool fractional= (anr != floor(anr)); int neg= (nr < 0.0) ? 1 : 0; - if (local_char_length > 4 && local_char_length < 32 && - (anr < 1.0 ? anr > 1/(log_10[max(0,(int) local_char_length-neg-2)]) /* -2 for "0." */ - : anr < log_10[local_char_length-neg]-1)) - use_scientific_notation= FALSE; - - length= (uint) my_sprintf(buff, (buff, "%-.*g", - (use_scientific_notation ? - max(0, (int)local_char_length-neg-5) : - local_char_length), - nr)); + uint max_length; + int exp; + uint digits; + uint i; + + /* Calculate the exponent from the 'e'-format conversion */ + if (anr < 1.0 && anr > 0) + { + for (exp= 0; anr < 1e-100; exp-= 100, anr*= 1e100); + for (; anr < 1e-10; exp-= 10, anr*= 1e10); + for (i= 1; anr < 1 / log_10[i]; exp--, i++); + exp--; + } + else + { + for (exp= 0; anr > 1e100; exp+= 100, anr/= 1e100); + for (; anr > 1e10; exp+= 10, anr/= 1e10); + for (i= 1; anr > log_10[i]; exp++, i++); + } + + max_length= local_char_length - neg; + + /* + Since in sprintf("%g") precision means the number of significant digits, + calculate the maximum number of significant digits if the 'f'-format + would be used (+1 for decimal point if the number has a fractional part). + */ + digits= max(0, (int) max_length - fractional); + /* + If the exponent is negative, decrease digits by the number of leading zeros + after the decimal point that do not count as significant digits. + */ + if (exp < 0) + digits= max(0, (int) digits + exp); + /* + 'e'-format is used only if the exponent is less than -4 or greater than or + equal to the precision. In this case we need to adjust the number of + significant digits to take "e+NN" + decimal point into account (hence -5). + We also have to reserve one additional character if abs(exp) >= 100. + */ + if (exp >= (int) digits || exp < -4) + digits= max(0, (int) (max_length - 5 - (exp >= 100 || exp <= -100))); + + /* Limit precision to DBL_DIG to avoid garbage past significant digits */ + set_if_smaller(digits, DBL_DIG); + + length= (uint) my_sprintf(buff, (buff, "%-.*g", digits, nr)); + +#ifdef __WIN__ + /* + Windows always zero-pads the exponent to 3 digits, we want to remove the + leading 0 to match the sprintf() output on other platforms. + */ + if ((exp >= (int) digits || exp < -4) && exp > -100 && exp < 100) + { + DBUG_ASSERT(length >= 6); /* 1e+NNN */ + uint tmp= length - 3; + buff[tmp]= buff[tmp + 1]; + tmp++; + buff[tmp]= buff[tmp + 1]; + length--; + } +#endif + /* +1 below is because "precision" in %g above means the max. number of significant digits, not the output width. diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 633db8367c1..3c738fe9ff1 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2626,6 +2626,23 @@ bool Item_func_case::fix_fields(THD *thd, Item **ref) } +void Item_func_case::agg_str_lengths(Item* arg) +{ + set_if_bigger(max_length, arg->max_length); + set_if_bigger(decimals, arg->decimals); + unsigned_flag= unsigned_flag && arg->unsigned_flag; +} + + +void Item_func_case::agg_num_lengths(Item *arg) +{ + uint len= my_decimal_length_to_precision(arg->max_length, arg->decimals, + arg->unsigned_flag) - arg->decimals; + set_if_bigger(max_length, len); + set_if_bigger(decimals, arg->decimals); + unsigned_flag= unsigned_flag && arg->unsigned_flag; +} + void Item_func_case::fix_length_and_dec() { @@ -2689,15 +2706,22 @@ void Item_func_case::fix_length_and_dec() max_length=0; decimals=0; - for (uint i=0 ; i < ncases ; i+=2) + unsigned_flag= TRUE; + if (cached_result_type == STRING_RESULT) { - set_if_bigger(max_length,args[i+1]->max_length); - set_if_bigger(decimals,args[i+1]->decimals); + for (uint i= 0; i < ncases; i+= 2) + agg_str_lengths(args[i + 1]); + if (else_expr_num != -1) + agg_str_lengths(args[else_expr_num]); } - if (else_expr_num != -1) + else { - set_if_bigger(max_length,args[else_expr_num]->max_length); - set_if_bigger(decimals,args[else_expr_num]->decimals); + for (uint i= 0; i < ncases; i+= 2) + agg_num_lengths(args[i + 1]); + if (else_expr_num != -1) + agg_num_lengths(args[else_expr_num]); + max_length= my_decimal_precision_to_length(max_length + decimals, decimals, + unsigned_flag); } } @@ -2901,7 +2925,7 @@ static inline int cmp_ulongs (ulonglong a_val, ulonglong b_val) SYNOPSIS cmp_longlong() - cmp_arg an argument passed to the calling function (qsort2) + cmp_arg an argument passed to the calling function (my_qsort2) a left argument b right argument diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 8df0e1af331..188d87a69ca 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -742,7 +742,7 @@ public: virtual uchar *get_value(Item *item)=0; void sort() { - qsort2(base,used_count,size,compare,collation); + my_qsort2(base,used_count,size,compare,collation); } int find(Item *item); @@ -1145,6 +1145,8 @@ public: Item *find_item(String *str); CHARSET_INFO *compare_collation() { return cmp_collation.collation; } void cleanup(); + void agg_str_lengths(Item *arg); + void agg_num_lengths(Item *arg); }; /* diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 3608568bd5e..0d7cd66acff 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -657,7 +657,12 @@ public: } String* val_str(String* str); const char *func_name() const { return "inet_ntoa"; } - void fix_length_and_dec() { decimals = 0; max_length=3*8+7; maybe_null=1;} + void fix_length_and_dec() + { + decimals= 0; + max_length= 3 * 8 + 7; + maybe_null= 1; + } }; class Item_func_quote :public Item_str_func diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index e7d513e9d6a..3d4a6de83ac 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -3241,38 +3241,42 @@ get_date_time_result_type(const char *format, uint length) void Item_func_str_to_date::fix_length_and_dec() { - char format_buff[64]; - String format_str(format_buff, sizeof(format_buff), &my_charset_bin), *format; maybe_null= 1; decimals=0; cached_field_type= MYSQL_TYPE_DATETIME; max_length= MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; cached_timestamp_type= MYSQL_TIMESTAMP_NONE; - format= args[1]->val_str(&format_str); - if (!args[1]->null_value && (const_item= args[1]->const_item())) + if ((const_item= args[1]->const_item())) { - cached_format_type= get_date_time_result_type(format->ptr(), - format->length()); - switch (cached_format_type) { - case DATE_ONLY: - cached_timestamp_type= MYSQL_TIMESTAMP_DATE; - cached_field_type= MYSQL_TYPE_DATE; - max_length= MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; - break; - case TIME_ONLY: - case TIME_MICROSECOND: - cached_timestamp_type= MYSQL_TIMESTAMP_TIME; - cached_field_type= MYSQL_TYPE_TIME; - max_length= MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; - break; - default: - cached_timestamp_type= MYSQL_TIMESTAMP_DATETIME; - cached_field_type= MYSQL_TYPE_DATETIME; - break; + char format_buff[64]; + String format_str(format_buff, sizeof(format_buff), &my_charset_bin); + String *format= args[1]->val_str(&format_str); + if (!args[1]->null_value) + { + cached_format_type= get_date_time_result_type(format->ptr(), + format->length()); + switch (cached_format_type) { + case DATE_ONLY: + cached_timestamp_type= MYSQL_TIMESTAMP_DATE; + cached_field_type= MYSQL_TYPE_DATE; + max_length= MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN; + break; + case TIME_ONLY: + case TIME_MICROSECOND: + cached_timestamp_type= MYSQL_TIMESTAMP_TIME; + cached_field_type= MYSQL_TYPE_TIME; + max_length= MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN; + break; + default: + cached_timestamp_type= MYSQL_TIMESTAMP_DATETIME; + cached_field_type= MYSQL_TYPE_DATETIME; + break; + } } } } + bool Item_func_str_to_date::get_date(MYSQL_TIME *ltime, uint fuzzy_date) { DATE_TIME_FORMAT date_time_format; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index c67687b2bde..761897f21b5 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -4463,8 +4463,8 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, ROR_SCAN_INFO's. Step 2: Get best ROR-intersection using an approximate algorithm. */ - qsort(tree->ror_scans, tree->n_ror_scans, sizeof(ROR_SCAN_INFO*), - (qsort_cmp)cmp_ror_scan_info); + my_qsort(tree->ror_scans, tree->n_ror_scans, sizeof(ROR_SCAN_INFO*), + (qsort_cmp)cmp_ror_scan_info); DBUG_EXECUTE("info",print_ror_scans_arr(param->table, "ordered", tree->ror_scans, tree->ror_scans_end);); @@ -4656,8 +4656,8 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, bitmap_get_first(&(*scan)->covered_fields); } - qsort(ror_scan_mark, ror_scans_end-ror_scan_mark, sizeof(ROR_SCAN_INFO*), - (qsort_cmp)cmp_ror_scan_info_covering); + my_qsort(ror_scan_mark, ror_scans_end-ror_scan_mark, sizeof(ROR_SCAN_INFO*), + (qsort_cmp)cmp_ror_scan_info_covering); DBUG_EXECUTE("info", print_ror_scans_arr(param->table, "remaining scans", diff --git a/sql/partition_info.cc b/sql/partition_info.cc index ab887d5dda0..86d50cdf524 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -666,8 +666,8 @@ bool partition_info::check_list_constants() if (fixed && no_list_values) { bool first= TRUE; - qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY), - &list_part_cmp); + my_qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY), + &list_part_cmp); i= 0; LINT_INIT(prev_value); diff --git a/sql/records.cc b/sql/records.cc index 0bf815e4073..349cc4a8329 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -567,7 +567,8 @@ static int rr_from_cache(READ_RECORD *info) int3store(ref_position,(long) i); ref_position+=3; } - qsort(info->read_positions,length,info->struct_length,(qsort_cmp) rr_cmp); + my_qsort(info->read_positions, length, info->struct_length, + (qsort_cmp) rr_cmp); position=info->read_positions; for (i=0 ; i < length ; i++) diff --git a/sql/set_var.cc b/sql/set_var.cc index d408b2de64e..de5f1fbcd0f 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -164,7 +164,8 @@ static sys_var_character_set_sv sys_character_set_server(&vars, "character_set_s sys_var_const_str sys_charset_system(&vars, "character_set_system", (char *)my_charset_utf8_general_ci.name); static sys_var_character_set_database sys_character_set_database(&vars, "character_set_database"); -static sys_var_character_set_sv sys_character_set_client(&vars, "character_set_client", +static sys_var_character_set_client sys_character_set_client(&vars, + "character_set_client", &SV::character_set_client, &default_charset_info); static sys_var_character_set_sv sys_character_set_connection(&vars, "character_set_connection", @@ -1865,6 +1866,21 @@ CHARSET_INFO **sys_var_character_set_sv::ci_ptr(THD *thd, enum_var_type type) } +bool sys_var_character_set_client::check(THD *thd, set_var *var) +{ + if (sys_var_character_set_sv::check(thd, var)) + return 1; + /* Currently, UCS-2 cannot be used as a client character set */ + if (var->save_result.charset->mbminlen > 1) + { + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, + var->save_result.charset->csname); + return 1; + } + return 0; +} + + CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd, enum_var_type type) { @@ -2106,18 +2122,24 @@ void sys_var_log_state::set_default(THD *thd, enum_var_type type) static int sys_check_log_path(THD *thd, set_var *var) { - char path[FN_REFLEN]; + char path[FN_REFLEN], buff[FN_REFLEN]; MY_STAT f_stat; - const char *var_path= var->value->str_value.ptr(); + String str(buff, sizeof(buff), system_charset_info), *res; + const char *log_file_str; + + if (!(res= var->value->val_str(&str))) + goto err; + + log_file_str= res->c_ptr(); bzero(&f_stat, sizeof(MY_STAT)); - (void) unpack_filename(path, var_path); + (void) unpack_filename(path, log_file_str); if (my_stat(path, &f_stat, MYF(0))) { /* Check if argument is a file and we have 'write' permission */ if (!MY_S_ISREG(f_stat.st_mode) || !(f_stat.st_mode & MY_S_IWRITE)) - return -1; + goto err; } else { @@ -2126,11 +2148,16 @@ static int sys_check_log_path(THD *thd, set_var *var) Check if directory exists and we have permission to create file & write to file */ - (void) dirname_part(path, var_path, &path_length); + (void) dirname_part(path, log_file_str, &path_length); if (my_access(path, (F_OK|W_OK))) - return -1; + goto err; } return 0; + +err: + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, + res ? log_file_str : "NULL"); + return 1; } @@ -2283,6 +2310,13 @@ uchar *sys_var_log_output::value_ptr(THD *thd, enum_var_type type, int set_var_collation_client::check(THD *thd) { + /* Currently, UCS-2 cannot be used as a client character set */ + if (character_set_client->mbminlen > 1) + { + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "character_set_client", + character_set_client->csname); + return 1; + } return 0; } @@ -2904,7 +2938,8 @@ SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted) /* sort into order */ if (sorted) - qsort(result, count + fixed_count, sizeof(SHOW_VAR), (qsort_cmp)show_cmp); + my_qsort(result, count + fixed_count, sizeof(SHOW_VAR), + (qsort_cmp) show_cmp); /* make last element empty */ bzero(show, sizeof(SHOW_VAR)); diff --git a/sql/set_var.h b/sql/set_var.h index eb2c893c89e..0e282212a3f 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -667,6 +667,20 @@ public: }; +class sys_var_character_set_client: public sys_var_character_set_sv +{ +public: + sys_var_character_set_client(sys_var_chain *chain, const char *name_arg, + CHARSET_INFO *SV::*offset_arg, + CHARSET_INFO **global_default_arg, + bool is_nullable= 0) + : sys_var_character_set_sv(chain, name_arg, offset_arg, global_default_arg, + is_nullable) + { } + bool check(THD *thd, set_var *var); +}; + + class sys_var_character_set_database :public sys_var_character_set { public: diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 311b76c6149..2e61b5559da 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -365,8 +365,8 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) #endif VOID(push_dynamic(&acl_hosts,(uchar*) &host)); } - qsort((uchar*) dynamic_element(&acl_hosts,0,ACL_HOST*),acl_hosts.elements, - sizeof(ACL_HOST),(qsort_cmp) acl_compare); + my_qsort((uchar*) dynamic_element(&acl_hosts,0,ACL_HOST*),acl_hosts.elements, + sizeof(ACL_HOST),(qsort_cmp) acl_compare); end_read_record(&read_record_info); freeze_size(&acl_hosts); @@ -553,8 +553,8 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) allow_all_hosts=1; // Anyone can connect } } - qsort((uchar*) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, - sizeof(ACL_USER),(qsort_cmp) acl_compare); + my_qsort((uchar*) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, + sizeof(ACL_USER),(qsort_cmp) acl_compare); end_read_record(&read_record_info); freeze_size(&acl_users); @@ -612,8 +612,8 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) #endif VOID(push_dynamic(&acl_dbs,(uchar*) &db)); } - qsort((uchar*) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements, - sizeof(ACL_DB),(qsort_cmp) acl_compare); + my_qsort((uchar*) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements, + sizeof(ACL_DB),(qsort_cmp) acl_compare); end_read_record(&read_record_info); freeze_size(&acl_dbs); init_check_host(); @@ -1243,8 +1243,8 @@ static void acl_insert_user(const char *user, const char *host, if (!acl_user.host.hostname || (acl_user.host.hostname[0] == wild_many && !acl_user.host.hostname[1])) allow_all_hosts=1; // Anyone can connect /* purecov: tested */ - qsort((uchar*) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, - sizeof(ACL_USER),(qsort_cmp) acl_compare); + my_qsort((uchar*) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, + sizeof(ACL_USER),(qsort_cmp) acl_compare); /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ rebuild_check_host(); @@ -1306,8 +1306,8 @@ static void acl_insert_db(const char *user, const char *host, const char *db, acl_db.access=privileges; acl_db.sort=get_sort(3,acl_db.host.hostname,acl_db.db,acl_db.user); VOID(push_dynamic(&acl_dbs,(uchar*) &acl_db)); - qsort((uchar*) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements, - sizeof(ACL_DB),(qsort_cmp) acl_compare); + my_qsort((uchar*) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements, + sizeof(ACL_DB),(qsort_cmp) acl_compare); } diff --git a/sql/sql_array.h b/sql/sql_array.h index ab6fdd0c5c0..e1b22921519 100644 --- a/sql/sql_array.h +++ b/sql/sql_array.h @@ -62,7 +62,7 @@ public: void sort(CMP_FUNC cmp_func) { - qsort(array.buffer, array.elements, sizeof(Elem), (qsort_cmp)cmp_func); + my_qsort(array.buffer, array.elements, sizeof(Elem), (qsort_cmp)cmp_func); } }; diff --git a/sql/sql_help.cc b/sql/sql_help.cc index c1962c8c650..0d633ce86ac 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -528,7 +528,7 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol, List_iterator<String> it(*names); for (pos= pointers; pos!=end; (*pos++= it++)); - qsort(pointers,names->elements,sizeof(String*),string_ptr_cmp); + my_qsort(pointers,names->elements,sizeof(String*),string_ptr_cmp); for (pos= pointers; pos!=end; pos++) { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 8ed658df90d..8241fa4791a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7031,8 +7031,15 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, bool error= TRUE; // Error message is given DBUG_ENTER("create_table_precheck"); + /* + Require CREATE [TEMPORARY] privilege on new table; for + CREATE TABLE ... SELECT, also require INSERT. + */ + want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ? - CREATE_TMP_ACL : CREATE_ACL); + CREATE_TMP_ACL : CREATE_ACL) | + (select_lex->item_list.elements ? INSERT_ACL : 0); + if (check_access(thd, want_priv, create_table->db, &create_table->grant.privilege, 0, 0, test(create_table->schema_table)) || diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 952b94e6b6d..960dda485be 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3723,7 +3723,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, { KEYUSE key_end,*prev,*save_pos,*use; - qsort(keyuse->buffer,keyuse->elements,sizeof(KEYUSE), + my_qsort(keyuse->buffer,keyuse->elements,sizeof(KEYUSE), (qsort_cmp) sort_keyuse); bzero((char*) &key_end,sizeof(key_end)); /* Add for easy testing */ @@ -4492,8 +4492,9 @@ choose_plan(JOIN *join, table_map join_tables) Apply heuristic: pre-sort all access plans with respect to the number of records accessed. */ - qsort(join->best_ref + join->const_tables, join->tables - join->const_tables, - sizeof(JOIN_TAB*), straight_join?join_tab_cmp_straight:join_tab_cmp); + my_qsort(join->best_ref + join->const_tables, + join->tables - join->const_tables, sizeof(JOIN_TAB*), + straight_join ? join_tab_cmp_straight : join_tab_cmp); if (straight_join) { @@ -4540,6 +4541,17 @@ choose_plan(JOIN *join, table_map join_tables) ptr1 pointer to first JOIN_TAB object ptr2 pointer to second JOIN_TAB object + NOTES + The order relation implemented by join_tab_cmp() is not transitive, + i.e. it is possible to choose such a, b and c that (a < b) && (b < c) + but (c < a). This implies that result of a sort using the relation + implemented by join_tab_cmp() depends on the order in which + elements are compared, i.e. the result is implementation-specific. + Example: + a: dependent = 0x0 table->map = 0x1 found_records = 3 ptr = 0x907e6b0 + b: dependent = 0x0 table->map = 0x2 found_records = 3 ptr = 0x907e838 + c: dependent = 0x6 table->map = 0x10 found_records = 2 ptr = 0x907ecd0 + RETURN 1 if first is bigger -1 if second is bigger @@ -6440,7 +6452,15 @@ make_join_readinfo(JOIN *join, ulonglong options) else if (!table->covering_keys.is_clear_all() && !(tab->select && tab->select->quick)) { // Only read index tree - tab->index=find_shortest_key(table, & table->covering_keys); + /* + See bug #26447: "Using the clustered index for a table scan + is always faster than using a secondary index". + */ + if (table->s->primary_key != MAX_KEY && + table->file->primary_key_is_clustered()) + tab->index= table->s->primary_key; + else + tab->index=find_shortest_key(table, & table->covering_keys); tab->read_first_record= join_read_first; tab->type=JT_NEXT; // Read with index_first / index_next } @@ -9201,9 +9221,43 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, new_field->set_derivation(item->collation.derivation); break; case DECIMAL_RESULT: - new_field= new Field_new_decimal(item->max_length, maybe_null, item->name, - item->decimals, item->unsigned_flag); + { + uint8 dec= item->decimals; + uint8 intg= ((Item_decimal *) item)->decimal_precision() - dec; + uint8 len= item->max_length; + + /* + Trying to put too many digits overall in a DECIMAL(prec,dec) + will always throw a warning. We must limit dec to + DECIMAL_MAX_SCALE however to prevent an assert() later. + */ + + if (dec > 0) + { + signed int overflow; + + dec= min(dec, DECIMAL_MAX_SCALE); + + /* + If the value still overflows the field with the corrected dec, + we'll throw out decimals rather than integers. This is still + bad and of course throws a truncation warning. + +1: for decimal point + */ + + overflow= my_decimal_precision_to_length(intg + dec, dec, + item->unsigned_flag) - len; + + if (overflow > 0) + dec= max(0, dec - overflow); // too long, discard fract + else + len -= item->decimals - dec; // corrected value fits + } + + new_field= new Field_new_decimal(len, maybe_null, item->name, + dec, item->unsigned_flag); break; + } case ROW_RESULT: default: // This case should never be choosen diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 91acd8d20a3..d198ddde222 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1805,7 +1805,8 @@ bool quick_rm_table(handlerton *base,const char *db, /* Sort keys in the following order: - PRIMARY KEY - - UNIQUE keyws where all column are NOT NULL + - UNIQUE keys where all column are NOT NULL + - UNIQUE keys that don't contain partial segments - Other UNIQUE keys - Normal keys - Fulltext keys @@ -1816,26 +1817,31 @@ bool quick_rm_table(handlerton *base,const char *db, static int sort_keys(KEY *a, KEY *b) { - if (a->flags & HA_NOSAME) + ulong a_flags= a->flags, b_flags= b->flags; + + if (a_flags & HA_NOSAME) { - if (!(b->flags & HA_NOSAME)) + if (!(b_flags & HA_NOSAME)) return -1; - if ((a->flags ^ b->flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) + if ((a_flags ^ b_flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) { /* Sort NOT NULL keys before other keys */ - return (a->flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1; + return (a_flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1; } if (a->name == primary_key_name) return -1; if (b->name == primary_key_name) return 1; + /* Sort keys don't containing partial segments before others */ + if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG) + return (a_flags & HA_KEY_HAS_PART_KEY_SEG) ? 1 : -1; } - else if (b->flags & HA_NOSAME) + else if (b_flags & HA_NOSAME) return 1; // Prefer b - if ((a->flags ^ b->flags) & HA_FULLTEXT) + if ((a_flags ^ b_flags) & HA_FULLTEXT) { - return (a->flags & HA_FULLTEXT) ? 1 : -1; + return (a_flags & HA_FULLTEXT) ? 1 : -1; } /* Prefer original key order. usable_key_parts contains here @@ -2899,6 +2905,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, else key_info->flags|= HA_PACK_KEY; } + /* Check if the key segment is partial, set the key flag accordingly */ + if (length != sql_field->key_length) + key_info->flags|= HA_KEY_HAS_PART_KEY_SEG; + key_length+=length; key_part_info++; @@ -2954,8 +2964,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, DBUG_RETURN(TRUE); } /* Sort keys in optimized order */ - qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY), - (qsort_cmp) sort_keys); + my_qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY), + (qsort_cmp) sort_keys); create_info->null_bits= null_fields; DBUG_RETURN(FALSE); @@ -6884,23 +6894,35 @@ copy_data_between_tables(TABLE *from,TABLE *to, if (order) { - from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), - MYF(MY_FAE | MY_ZEROFILL)); - bzero((char*) &tables,sizeof(tables)); - tables.table= from; - tables.alias= tables.table_name= from->s->table_name.str; - tables.db= from->s->db.str; - error=1; + if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered()) + { + char warn_buff[MYSQL_ERRMSG_SIZE]; + my_snprintf(warn_buff, sizeof(warn_buff), + "ORDER BY ignored as there is a user-defined clustered index" + " in the table '%-.192s'", from->s->table_name.str); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, + warn_buff); + } + else + { + from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), + MYF(MY_FAE | MY_ZEROFILL)); + bzero((char *) &tables, sizeof(tables)); + tables.table= from; + tables.alias= tables.table_name= from->s->table_name.str; + tables.db= from->s->db.str; + error= 1; - if (thd->lex->select_lex.setup_ref_array(thd, order_num) || - setup_order(thd, thd->lex->select_lex.ref_pointer_array, - &tables, fields, all_fields, order) || - !(sortorder=make_unireg_sortorder(order, &length, NULL)) || - (from->sort.found_records = filesort(thd, from, sortorder, length, - (SQL_SELECT *) 0, HA_POS_ERROR, 1, - &examined_rows)) == - HA_POS_ERROR) - goto err; + if (thd->lex->select_lex.setup_ref_array(thd, order_num) || + setup_order(thd, thd->lex->select_lex.ref_pointer_array, + &tables, fields, all_fields, order) || + !(sortorder= make_unireg_sortorder(order, &length, NULL)) || + (from->sort.found_records= filesort(thd, from, sortorder, length, + (SQL_SELECT *) 0, HA_POS_ERROR, + 1, &examined_rows)) == + HA_POS_ERROR) + goto err; + } }; /* Tell handler that we have values for all columns in the to table */ diff --git a/sql/structs.h b/sql/structs.h index 09a3c4d7285..662d0a680b8 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -71,7 +71,7 @@ typedef struct st_key_part_info { /* Info about a key part */ typedef struct st_key { uint key_length; /* Tot length of key */ - uint flags; /* dupp key and pack flags */ + ulong flags; /* dupp key and pack flags */ uint key_parts; /* How many key_parts */ uint extra_length; uint usable_key_parts; /* Should normally be = key_parts */ diff --git a/sql/unireg.cc b/sql/unireg.cc index f2238d69973..dbdefd8d5b1 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -505,7 +505,7 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo, int2store(pos+6, key->block_size); pos+=8; key_parts+=key->key_parts; - DBUG_PRINT("loop", ("flags: %d key_parts: %d at 0x%lx", + DBUG_PRINT("loop", ("flags: %lu key_parts: %d at 0x%lx", key->flags, key->key_parts, (long) key->key_part)); for (key_part=key->key_part,key_part_end=key_part+key->key_parts ; diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index 6a87b8ecc72..0d9c019a19d 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -1203,8 +1203,8 @@ int ha_tina::rnd_end() The sort is needed when there were updates/deletes with random orders. It sorts so that we move the firts blocks to the beginning. */ - qsort(chain, (size_t)(chain_ptr - chain), sizeof(tina_set), - (qsort_cmp)sort_set); + my_qsort(chain, (size_t)(chain_ptr - chain), sizeof(tina_set), + (qsort_cmp)sort_set); off_t write_begin= 0, write_end; diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c index 15f4e1e1d34..5e7a955793f 100644 --- a/storage/myisam/ft_boolean_search.c +++ b/storage/myisam/ft_boolean_search.c @@ -576,8 +576,8 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, uchar *query, ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root, sizeof(FTB_WORD *)*ftb->queue.elements); memcpy(ftb->list, ftb->queue.root+1, sizeof(FTB_WORD *)*ftb->queue.elements); - qsort2(ftb->list, ftb->queue.elements, sizeof(FTB_WORD *), - (qsort2_cmp)FTB_WORD_cmp_list, ftb->charset); + my_qsort2(ftb->list, ftb->queue.elements, sizeof(FTB_WORD *), + (qsort2_cmp)FTB_WORD_cmp_list, ftb->charset); if (ftb->queue.elements<2) ftb->with_scan &= ~FTB_FLAG_TRUNC; ftb->state=READY; return ftb; diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c index 282fa6751d8..8df8c2da4eb 100644 --- a/storage/myisam/ft_nlq_search.c +++ b/storage/myisam/ft_nlq_search.c @@ -294,7 +294,8 @@ FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, uchar *query, &dptr, left_root_right); if (flags & FT_SORTED) - qsort2(dlist->doc, dlist->ndocs, sizeof(FT_DOC), (qsort2_cmp)&FT_DOC_cmp, 0); + my_qsort2(dlist->doc, dlist->ndocs, sizeof(FT_DOC), (qsort2_cmp)&FT_DOC_cmp, + 0); err: delete_tree(&aio.dtree); diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index dcedcf03f65..a557890a7b9 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -153,7 +153,7 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out, pos= table_arg->key_info; for (i= 0; i < share->keys; i++, pos++) { - keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL)); + keydef[i].flag= ((uint16) pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL)); keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ? (pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) : pos->algorithm; diff --git a/storage/myisam/myisampack.c b/storage/myisam/myisampack.c index 37428ddd279..7233ebbff80 100644 --- a/storage/myisam/myisampack.c +++ b/storage/myisam/myisampack.c @@ -3148,7 +3148,7 @@ static void fakebigcodes(HUFF_COUNTS *huff_counts, HUFF_COUNTS *end_count) cur_sort_p= sort_counts; while (cur_count_p < end_count_p) *(cur_sort_p++)= cur_count_p++; - (void) qsort(sort_counts, 256, sizeof(my_off_t*), (qsort_cmp) fakecmp); + (void) my_qsort(sort_counts, 256, sizeof(my_off_t*), (qsort_cmp) fakecmp); /* Assign faked counts. diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c index 941b6a7616c..d505d2633ce 100644 --- a/storage/myisam/sort.c +++ b/storage/myisam/sort.c @@ -650,8 +650,8 @@ static int NEAR_F write_keys(MI_SORT_PARAM *info, register uchar **sort_keys, uint sort_length=info->key_length; DBUG_ENTER("write_keys"); - qsort2((uchar*) sort_keys,count,sizeof(uchar*),(qsort2_cmp) info->key_cmp, - info); + my_qsort2((uchar*) sort_keys,count,sizeof(uchar*),(qsort2_cmp) info->key_cmp, + info); if (!my_b_inited(tempfile) && open_cached_file(tempfile, my_tmpdir(info->tmpdir), "ST", DISK_BUFFER_SIZE, info->sort_info->param->myf_rw)) @@ -693,8 +693,8 @@ static int NEAR_F write_keys_varlen(MI_SORT_PARAM *info, int err; DBUG_ENTER("write_keys_varlen"); - qsort2((uchar*) sort_keys,count,sizeof(uchar*),(qsort2_cmp) info->key_cmp, - info); + my_qsort2((uchar*) sort_keys,count,sizeof(uchar*),(qsort2_cmp) info->key_cmp, + info); if (!my_b_inited(tempfile) && open_cached_file(tempfile, my_tmpdir(info->tmpdir), "ST", DISK_BUFFER_SIZE, info->sort_info->param->myf_rw)) @@ -736,8 +736,8 @@ static int NEAR_F write_index(MI_SORT_PARAM *info, register uchar **sort_keys, { DBUG_ENTER("write_index"); - qsort2((uchar*) sort_keys,(size_t) count,sizeof(uchar*), - (qsort2_cmp) info->key_cmp,info); + my_qsort2((uchar*) sort_keys,(size_t) count,sizeof(uchar*), + (qsort2_cmp) info->key_cmp,info); while (count--) { if ((*info->key_write)(info,*sort_keys++)) diff --git a/storage/ndb/src/mgmsrv/Services.cpp b/storage/ndb/src/mgmsrv/Services.cpp index 9272b5ab532..eeae61025b1 100644 --- a/storage/ndb/src/mgmsrv/Services.cpp +++ b/storage/ndb/src/mgmsrv/Services.cpp @@ -968,7 +968,6 @@ printNodeStatus(OutputStream *output, MgmtSrvr &mgmsrv, enum ndb_mgm_node_type type) { NodeId nodeId = 0; - mgmsrv.updateStatus(); while(mgmsrv.getNextNodeId(&nodeId, type)) { enum ndb_mgm_node_status status; Uint32 startPhase = 0, @@ -1018,6 +1017,7 @@ MgmApiSession::getStatus(Parser<MgmApiSession>::Context &, m_output->println("node status"); SLEEP_ERROR_INSERTED(6); m_output->println("nodes: %d", noOfNodes); + m_mgmsrv.updateStatus(); SLEEP_ERROR_INSERTED(7); printNodeStatus(m_output, m_mgmsrv, NDB_MGM_NODE_TYPE_NDB); printNodeStatus(m_output, m_mgmsrv, NDB_MGM_NODE_TYPE_MGM); diff --git a/storage/ndb/src/ndbapi/ClusterMgr.cpp b/storage/ndb/src/ndbapi/ClusterMgr.cpp index 448bc1025e8..f5cc44f70d7 100644 --- a/storage/ndb/src/ndbapi/ClusterMgr.cpp +++ b/storage/ndb/src/ndbapi/ClusterMgr.cpp @@ -204,7 +204,10 @@ ClusterMgr::forceHB() theFacade.sendSignalUnCond(&signal, nodeId); } - NdbCondition_WaitTimeout(waitForHBCond, theFacade.theMutexPtr, 1000); + /* Wait for nodes to reply - if any heartbeats was sent */ + if (!waitForHBFromNodes.isclear()) + NdbCondition_WaitTimeout(waitForHBCond, theFacade.theMutexPtr, 1000); + waitingForHB= false; #ifdef DEBUG_REG ndbout << "Still waiting for HB from " << waitForHBFromNodes.getText(buf) << endl; diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 5dce4aad75e..7de00025eda 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -845,6 +845,7 @@ size_t my_long10_to_str_8bit(CHARSET_INFO *cs __attribute__((unused)), register char *p, *e; long int new_val; uint sign=0; + unsigned long int uval = (unsigned long int) val; e = p = &buffer[sizeof(buffer)-1]; *p= 0; @@ -853,15 +854,16 @@ size_t my_long10_to_str_8bit(CHARSET_INFO *cs __attribute__((unused)), { if (val < 0) { - val= -(unsigned long int)val; + /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ + uval= (unsigned long int)0 - uval; *dst++= '-'; len--; sign= 1; } } - new_val = (long) ((unsigned long int) val / 10); - *--p = '0'+ (char) ((unsigned long int) val - (unsigned long) new_val * 10); + new_val = (long) (uval / 10); + *--p = '0'+ (char) (uval - (unsigned long) new_val * 10); val = new_val; while (val != 0) @@ -885,12 +887,14 @@ size_t my_longlong10_to_str_8bit(CHARSET_INFO *cs __attribute__((unused)), register char *p, *e; long long_val; uint sign= 0; + ulonglong uval = (ulonglong)val; if (radix < 0) { if (val < 0) { - val = -(ulonglong)val; + /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ + uval = (ulonglong)0 - uval; *dst++= '-'; len--; sign= 1; @@ -900,22 +904,22 @@ size_t my_longlong10_to_str_8bit(CHARSET_INFO *cs __attribute__((unused)), e = p = &buffer[sizeof(buffer)-1]; *p= 0; - if (val == 0) + if (uval == 0) { *--p= '0'; len= 1; goto cnv; } - while ((ulonglong) val > (ulonglong) LONG_MAX) + while (uval > (ulonglong) LONG_MAX) { - ulonglong quo=(ulonglong) val/(uint) 10; - uint rem= (uint) (val- quo* (uint) 10); + ulonglong quo= uval/(uint) 10; + uint rem= (uint) (uval- quo* (uint) 10); *--p = '0' + rem; - val= quo; + uval= quo; } - long_val= (long) val; + long_val= (long) uval; while (long_val != 0) { long quo= long_val/10; @@ -1561,14 +1565,18 @@ my_strntoull10rnd_8bit(CHARSET_INFO *cs __attribute__((unused)), } else addon= (*str >= '5'); - for ( ; str < end && (ch= (uchar) (*str - '0')) < 10; str++) + if (!dot) { - if (!dot) - shift++; + for ( ; str < end && (ch= (uchar) (*str - '0')) < 10; shift++, str++); + if (str < end && *str == '.') + { + str++; + for ( ; str < end && (ch= (uchar) (*str - '0')) < 10; str++); + } } - if (str < end && *str == '.' && !dot) + else { - str++; + shift= dot - str; for ( ; str < end && (ch= (uchar) (*str - '0')) < 10; str++); } goto exp; diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 1df8221072e..d1579afe4c2 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1019,6 +1019,7 @@ size_t my_l10tostr_ucs2(CHARSET_INFO *cs, register char *p, *db, *de; long int new_val; int sl=0; + unsigned long int uval = (unsigned long int) val; p = &buffer[sizeof(buffer)-1]; *p='\0'; @@ -1028,12 +1029,13 @@ size_t my_l10tostr_ucs2(CHARSET_INFO *cs, if (val < 0) { sl = 1; - val = -val; + /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ + uval = (unsigned long int)0 - uval; } } - new_val = (long) ((unsigned long int) val / 10); - *--p = '0'+ (char) ((unsigned long int) val - (unsigned long) new_val * 10); + new_val = (long) (uval / 10); + *--p = '0'+ (char) (uval - (unsigned long) new_val * 10); val = new_val; while (val != 0) @@ -1067,34 +1069,36 @@ size_t my_ll10tostr_ucs2(CHARSET_INFO *cs __attribute__((unused)), register char *p, *db, *de; long long_val; int sl=0; + ulonglong uval= (ulonglong) val; if (radix < 0) { if (val < 0) { sl=1; - val = -val; + /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ + uval = (ulonglong)0 - uval; } } p = &buffer[sizeof(buffer)-1]; *p='\0'; - if (val == 0) + if (uval == 0) { *--p='0'; goto cnv; } - while ((ulonglong) val > (ulonglong) LONG_MAX) + while (uval > (ulonglong) LONG_MAX) { - ulonglong quo=(ulonglong) val/(size_t) 10; - uint rem= (uint) (val- quo* (uint) 10); + ulonglong quo= uval/(uint) 10; + uint rem= (uint) (uval- quo* (uint) 10); *--p = '0' + rem; - val= quo; + uval= quo; } - long_val= (long) val; + long_val= (long) uval; while (long_val != 0) { long quo= long_val/10; diff --git a/strings/int2str.c b/strings/int2str.c index 9fc53032819..fba98aac3f1 100644 --- a/strings/int2str.c +++ b/strings/int2str.c @@ -57,6 +57,7 @@ int2str(register long int val, register char *dst, register int radix, register char *p; long int new_val; char *dig_vec= upcase ? _dig_vec_upper : _dig_vec_lower; + ulong uval= (ulong) val; if (radix < 0) { @@ -65,7 +66,8 @@ int2str(register long int val, register char *dst, register int radix, if (val < 0) { *dst++ = '-'; - val = -val; + /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ + uval = (ulong)0 - uval; } radix = -radix; } @@ -86,8 +88,8 @@ int2str(register long int val, register char *dst, register int radix, */ p = &buffer[sizeof(buffer)-1]; *p = '\0'; - new_val=(ulong) val / (ulong) radix; - *--p = dig_vec[(uchar) ((ulong) val- (ulong) new_val*(ulong) radix)]; + new_val= uval / (ulong) radix; + *--p = dig_vec[(uchar) (uval- (ulong) new_val*(ulong) radix)]; val = new_val; #ifdef HAVE_LDIV while (val != 0) @@ -133,20 +135,22 @@ char *int10_to_str(long int val,char *dst,int radix) char buffer[65]; register char *p; long int new_val; + unsigned long int uval = (unsigned long int) val; if (radix < 0) /* -10 */ { if (val < 0) { *dst++ = '-'; - val = -val; + /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ + uval = (unsigned long int)0 - uval; } } p = &buffer[sizeof(buffer)-1]; *p = '\0'; - new_val= (long) ((unsigned long int) val / 10); - *--p = '0'+ (char) ((unsigned long int) val - (unsigned long) new_val * 10); + new_val= (long) (uval / 10); + *--p = '0'+ (char) (uval - (unsigned long) new_val * 10); val = new_val; while (val != 0) diff --git a/strings/longlong2str.c b/strings/longlong2str.c index c464abcfccd..d7de5bb0f7c 100644 --- a/strings/longlong2str.c +++ b/strings/longlong2str.c @@ -51,13 +51,15 @@ char *longlong2str(longlong val,char *dst,int radix) char buffer[65]; register char *p; long long_val; + ulonglong uval= (ulonglong) val; if (radix < 0) { if (radix < -36 || radix > -2) return (char*) 0; if (val < 0) { *dst++ = '-'; - val = -val; + /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ + uval = (ulonglong)0 - uval; } radix = -radix; } @@ -65,7 +67,7 @@ char *longlong2str(longlong val,char *dst,int radix) { if (radix > 36 || radix < 2) return (char*) 0; } - if (val == 0) + if (uval == 0) { *dst++='0'; *dst='\0'; @@ -74,14 +76,14 @@ char *longlong2str(longlong val,char *dst,int radix) p = &buffer[sizeof(buffer)-1]; *p = '\0'; - while ((ulonglong) val > (ulonglong) LONG_MAX) + while (uval > (ulonglong) LONG_MAX) { - ulonglong quo=(ulonglong) val/(uint) radix; - uint rem= (uint) (val- quo* (uint) radix); + ulonglong quo= uval/(uint) radix; + uint rem= (uint) (uval- quo* (uint) radix); *--p = _dig_vec_upper[rem]; - val= quo; + uval= quo; } - long_val= (long) val; + long_val= (long) uval; while (long_val != 0) { long quo= long_val/radix; @@ -100,17 +102,19 @@ char *longlong10_to_str(longlong val,char *dst,int radix) char buffer[65]; register char *p; long long_val; + ulonglong uval= (ulonglong) val; if (radix < 0) { if (val < 0) { *dst++ = '-'; - val = -val; + /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ + uval = (ulonglong)0 - uval; } } - if (val == 0) + if (uval == 0) { *dst++='0'; *dst='\0'; @@ -119,14 +123,14 @@ char *longlong10_to_str(longlong val,char *dst,int radix) p = &buffer[sizeof(buffer)-1]; *p = '\0'; - while ((ulonglong) val > (ulonglong) LONG_MAX) + while (uval > (ulonglong) LONG_MAX) { - ulonglong quo=(ulonglong) val/(uint) 10; - uint rem= (uint) (val- quo* (uint) 10); + ulonglong quo= uval/(uint) 10; + uint rem= (uint) (uval- quo* (uint) 10); *--p = _dig_vec_upper[rem]; - val= quo; + uval= quo; } - long_val= (long) val; + long_val= (long) uval; while (long_val != 0) { long quo= long_val/10; |